]> git.mxchange.org Git - flightgear.git/commitdiff
sync. with JSBSim v. 2.0
authorehofman <ehofman>
Thu, 12 Jan 2006 15:04:22 +0000 (15:04 +0000)
committerehofman <ehofman>
Thu, 12 Jan 2006 15:04:22 +0000 (15:04 +0000)
195 files changed:
configure.ac
src/FDM/JSBSim/FGFDMExec.cpp
src/FDM/JSBSim/FGFDMExec.h
src/FDM/JSBSim/FGJSBBase.cpp
src/FDM/JSBSim/FGJSBBase.h
src/FDM/JSBSim/FGLocation.h [deleted file]
src/FDM/JSBSim/FGMassBalance.cpp [deleted file]
src/FDM/JSBSim/FGMassBalance.h [deleted file]
src/FDM/JSBSim/FGMatrix33.cpp [deleted file]
src/FDM/JSBSim/FGMatrix33.h [deleted file]
src/FDM/JSBSim/FGModel.cpp [deleted file]
src/FDM/JSBSim/FGModel.h [deleted file]
src/FDM/JSBSim/FGNozzle.cpp [deleted file]
src/FDM/JSBSim/FGNozzle.h [deleted file]
src/FDM/JSBSim/FGOutput.cpp [deleted file]
src/FDM/JSBSim/FGOutput.h [deleted file]
src/FDM/JSBSim/FGPiston.cpp [deleted file]
src/FDM/JSBSim/FGPiston.h [deleted file]
src/FDM/JSBSim/FGPropagate.cpp [deleted file]
src/FDM/JSBSim/FGPropagate.h [deleted file]
src/FDM/JSBSim/FGPropeller.cpp [deleted file]
src/FDM/JSBSim/FGPropeller.h [deleted file]
src/FDM/JSBSim/FGPropertyManager.cpp [deleted file]
src/FDM/JSBSim/FGPropertyManager.h [deleted file]
src/FDM/JSBSim/FGPropulsion.cpp [deleted file]
src/FDM/JSBSim/FGPropulsion.h [deleted file]
src/FDM/JSBSim/FGQuaternion.cpp [deleted file]
src/FDM/JSBSim/FGQuaternion.h [deleted file]
src/FDM/JSBSim/FGRocket.cpp [deleted file]
src/FDM/JSBSim/FGRocket.h [deleted file]
src/FDM/JSBSim/FGRotor.cpp [deleted file]
src/FDM/JSBSim/FGRotor.h [deleted file]
src/FDM/JSBSim/FGScript.cpp [deleted file]
src/FDM/JSBSim/FGScript.h [deleted file]
src/FDM/JSBSim/FGState.cpp
src/FDM/JSBSim/FGState.h
src/FDM/JSBSim/FGTable.cpp [deleted file]
src/FDM/JSBSim/FGTable.h [deleted file]
src/FDM/JSBSim/FGTank.cpp [deleted file]
src/FDM/JSBSim/FGTank.h [deleted file]
src/FDM/JSBSim/FGThruster.cpp [deleted file]
src/FDM/JSBSim/FGThruster.h [deleted file]
src/FDM/JSBSim/FGTrim.cpp [deleted file]
src/FDM/JSBSim/FGTrim.h [deleted file]
src/FDM/JSBSim/FGTrimAxis.cpp [deleted file]
src/FDM/JSBSim/FGTrimAxis.h [deleted file]
src/FDM/JSBSim/FGTurbine.cpp [deleted file]
src/FDM/JSBSim/FGTurbine.h [deleted file]
src/FDM/JSBSim/FGfdmSocket.cpp [deleted file]
src/FDM/JSBSim/FGfdmSocket.h [deleted file]
src/FDM/JSBSim/JSBSim.cxx
src/FDM/JSBSim/JSBSim.hxx
src/FDM/JSBSim/Makefile.am
src/FDM/JSBSim/Makefile.solo [deleted file]
src/FDM/JSBSim/README [deleted file]
src/FDM/JSBSim/filtersjb/FGCondition.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGCondition.h [deleted file]
src/FDM/JSBSim/filtersjb/FGDeadBand.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGDeadBand.h [deleted file]
src/FDM/JSBSim/filtersjb/FGFCSComponent.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGFCSComponent.h [deleted file]
src/FDM/JSBSim/filtersjb/FGFilter.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGFilter.h [deleted file]
src/FDM/JSBSim/filtersjb/FGGain.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGGain.h [deleted file]
src/FDM/JSBSim/filtersjb/FGGradient.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGGradient.h [deleted file]
src/FDM/JSBSim/filtersjb/FGKinemat.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGKinemat.h [deleted file]
src/FDM/JSBSim/filtersjb/FGSummer.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGSummer.h [deleted file]
src/FDM/JSBSim/filtersjb/FGSwitch.cpp [deleted file]
src/FDM/JSBSim/filtersjb/FGSwitch.h [deleted file]
src/FDM/JSBSim/initialization/FGInitialCondition.cpp [new file with mode: 0644]
src/FDM/JSBSim/initialization/FGInitialCondition.h [new file with mode: 0644]
src/FDM/JSBSim/initialization/FGTrim.cpp [new file with mode: 0644]
src/FDM/JSBSim/initialization/FGTrim.h [new file with mode: 0644]
src/FDM/JSBSim/initialization/FGTrimAxis.cpp [new file with mode: 0644]
src/FDM/JSBSim/initialization/FGTrimAxis.h [new file with mode: 0644]
src/FDM/JSBSim/initialization/Makefile.am [new file with mode: 0644]
src/FDM/JSBSim/input_output/FGGroundCallback.cpp [new file with mode: 0644]
src/FDM/JSBSim/input_output/FGGroundCallback.h [new file with mode: 0644]
src/FDM/JSBSim/input_output/FGPropertyManager.cpp [new file with mode: 0755]
src/FDM/JSBSim/input_output/FGPropertyManager.h [new file with mode: 0644]
src/FDM/JSBSim/input_output/FGScript.cpp [new file with mode: 0755]
src/FDM/JSBSim/input_output/FGScript.h [new file with mode: 0644]
src/FDM/JSBSim/input_output/FGXMLElement.cpp [new file with mode: 0755]
src/FDM/JSBSim/input_output/FGXMLElement.h [new file with mode: 0755]
src/FDM/JSBSim/input_output/FGXMLParse.cpp [new file with mode: 0755]
src/FDM/JSBSim/input_output/FGXMLParse.h [new file with mode: 0755]
src/FDM/JSBSim/input_output/FGfdmSocket.cpp [new file with mode: 0644]
src/FDM/JSBSim/input_output/FGfdmSocket.h [new file with mode: 0644]
src/FDM/JSBSim/input_output/Makefile.am [new file with mode: 0644]
src/FDM/JSBSim/math/FGColumnVector3.cpp [new file with mode: 0644]
src/FDM/JSBSim/math/FGColumnVector3.h [new file with mode: 0644]
src/FDM/JSBSim/math/FGFunction.cpp [new file with mode: 0755]
src/FDM/JSBSim/math/FGFunction.h [new file with mode: 0755]
src/FDM/JSBSim/math/FGLocation.cpp [new file with mode: 0644]
src/FDM/JSBSim/math/FGLocation.h [new file with mode: 0644]
src/FDM/JSBSim/math/FGMatrix33.cpp [new file with mode: 0644]
src/FDM/JSBSim/math/FGMatrix33.h [new file with mode: 0644]
src/FDM/JSBSim/math/FGParameter.h [new file with mode: 0755]
src/FDM/JSBSim/math/FGPropertyValue.cpp [new file with mode: 0755]
src/FDM/JSBSim/math/FGPropertyValue.h [new file with mode: 0755]
src/FDM/JSBSim/math/FGQuaternion.cpp [new file with mode: 0644]
src/FDM/JSBSim/math/FGQuaternion.h [new file with mode: 0644]
src/FDM/JSBSim/math/FGRealValue.cpp [new file with mode: 0755]
src/FDM/JSBSim/math/FGRealValue.h [new file with mode: 0755]
src/FDM/JSBSim/math/FGTable.cpp [new file with mode: 0644]
src/FDM/JSBSim/math/FGTable.h [new file with mode: 0644]
src/FDM/JSBSim/math/Makefile.am [new file with mode: 0644]
src/FDM/JSBSim/models/FGAerodynamics.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGAerodynamics.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGAircraft.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGAircraft.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGAtmosphere.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGAtmosphere.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGAuxiliary.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/FGAuxiliary.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGFCS.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGFCS.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGGroundReactions.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGGroundReactions.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGInertial.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGInertial.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGInput.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/FGInput.h [new file with mode: 0755]
src/FDM/JSBSim/models/FGLGear.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGLGear.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGMassBalance.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGMassBalance.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGModel.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGModel.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGOutput.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGOutput.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGPropagate.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGPropagate.h [new file with mode: 0644]
src/FDM/JSBSim/models/FGPropulsion.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/FGPropulsion.h [new file with mode: 0644]
src/FDM/JSBSim/models/Makefile.am [new file with mode: 0644]
src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/atmosphere/FGMSIS.h [new file with mode: 0755]
src/FDM/JSBSim/models/atmosphere/FGMSISData.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/atmosphere/FGMars.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/atmosphere/FGMars.h [new file with mode: 0755]
src/FDM/JSBSim/models/atmosphere/Makefile.am [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGCondition.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGCondition.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGDeadBand.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGFCSComponent.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/flight_control/FGFCSFunction.h [new file with mode: 0755]
src/FDM/JSBSim/models/flight_control/FGFilter.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGFilter.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGGain.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGGain.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGGradient.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGGradient.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGKinemat.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGKinemat.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGSensor.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/flight_control/FGSensor.h [new file with mode: 0755]
src/FDM/JSBSim/models/flight_control/FGSummer.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGSummer.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGSwitch.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/FGSwitch.h [new file with mode: 0644]
src/FDM/JSBSim/models/flight_control/Makefile.am [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGElectric.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGElectric.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGEngine.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGEngine.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGForce.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGForce.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGNozzle.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGNozzle.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGPiston.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGPiston.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGPropeller.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGPropeller.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGRocket.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGRocket.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGRotor.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGRotor.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGTank.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGTank.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGThruster.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGThruster.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGTurbine.cpp [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGTurbine.h [new file with mode: 0644]
src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/propulsion/FGTurboProp.h [new file with mode: 0755]
src/FDM/JSBSim/models/propulsion/Makefile.am [new file with mode: 0644]
src/Main/Makefile.am

index 38239fb464fe9f4704c3a369315818b30eda106b..3362342873f9f64ac8607c4a54729eac65ac15f4 100644 (file)
@@ -514,7 +514,13 @@ AC_CONFIG_FILES([ \
        src/FDM/ExternalNet/Makefile \
        src/FDM/ExternalPipe/Makefile \
        src/FDM/JSBSim/Makefile \
-       src/FDM/JSBSim/filtersjb/Makefile \
+       src/FDM/JSBSim/initialization/Makefile \
+       src/FDM/JSBSim/input_output/Makefile \
+       src/FDM/JSBSim/math/Makefile \
+        src/FDM/JSBSim/models/Makefile \
+       src/FDM/JSBSim/models/flight_control/Makefile \
+       src/FDM/JSBSim/models/atmosphere/Makefile \
+       src/FDM/JSBSim/models/propulsion/Makefile \
        src/FDM/LaRCsim/Makefile \
        src/FDM/SP/Makefile \
        src/FDM/UIUCModel/Makefile \
index ab37dac38e85e7ad9b76ec32644b1227fa1347f4..536baeee84c9690ae019d303e0d991ec7db326fd 100644 (file)
@@ -41,10 +41,6 @@ COMMENTS, REFERENCES,  and NOTES
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
 #ifdef FGFS
 #  include <simgear/compiler.h>
 #  include STL_IOSTREAM
@@ -60,21 +56,22 @@ INCLUDES
 
 #include "FGFDMExec.h"
 #include "FGState.h"
-#include "FGAtmosphere.h"
-#include "FGFCS.h"
-#include "FGGroundCallback.h"
-#include "FGPropulsion.h"
-#include "FGMassBalance.h"
-#include "FGGroundReactions.h"
-#include "FGAerodynamics.h"
-#include "FGInertial.h"
-#include "FGAircraft.h"
-#include "FGPropagate.h"
-#include "FGAuxiliary.h"
-#include "FGOutput.h"
-#include "FGConfigFile.h"
-#include "FGInitialCondition.h"
-#include "FGPropertyManager.h"
+#include <models/FGAtmosphere.h>
+#include <models/atmosphere/FGMSIS.h>
+#include <models/atmosphere/FGMars.h>
+#include <models/FGFCS.h>
+#include <models/FGPropulsion.h>
+#include <models/FGMassBalance.h>
+#include <models/FGGroundReactions.h>
+#include <models/FGAerodynamics.h>
+#include <models/FGInertial.h>
+#include <models/FGAircraft.h>
+#include <models/FGPropagate.h>
+#include <models/FGAuxiliary.h>
+#include <models/FGInput.h>
+#include <models/FGOutput.h>
+#include <initialization/FGInitialCondition.h>
+#include <input_output/FGPropertyManager.h>
 
 namespace JSBSim {
 
@@ -110,12 +107,13 @@ void checkTied ( FGPropertyManager *node )
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // Constructor
 
-FGFDMExec::FGFDMExec(FGPropertyManager* root)
+FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
 {
 
   Frame           = 0;
   FirstModel      = 0;
   Error           = 0;
+  GroundCallback  = 0;
   State           = 0;
   Atmosphere      = 0;
   FCS             = 0;
@@ -125,22 +123,25 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root)
   Inertial        = 0;
   GroundReactions = 0;
   Aircraft        = 0;
-  GroundCallback  = 0;
   Propagate       = 0;
   Auxiliary       = 0;
-  Output          = 0;
+  Input           = 0;
   IC              = 0;
   Trim            = 0;
 
   terminate = false;
-  frozen = false;
   modelLoaded = false;
   IsSlave = false;
+  holding = false;
+
 
   // Multiple FDM's are stopped for now.  We need to ensure that
   // the "user" instance always gets the zeroeth instance number,
   // because there may be instruments or scripts tied to properties
   // in the jsbsim[0] node.
+  // ToDo: it could be that when JSBSim is reset and a new FDM is wanted, that
+  // process might try setting FDMctr = 0. Then the line below would not need
+  // to be commented out.
   IdFDM = FDMctr;
   //FDMctr++;
 
@@ -151,31 +152,35 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root)
     debug_lvl = 1;
   }
 
-  if (root == 0)  master= new FGPropertyManager;
-  else            master = root;
+  if (Root == 0)  master= new FGPropertyManager;
+  else            master = Root;
 
   instance = master->GetNode("/fdm/jsbsim",IdFDM,true);
-
-
   Debug(0);
-
-  // this is here to catch errors in binding member functions
-  // to the property tree.
+  // this is to catch errors in binding member functions to the property tree.
   try {
     Allocate();
   } catch ( string msg ) {
     cout << "Caught error: " << msg << endl;
     exit(1);
   }
+
+  Constructing = true;
+  typedef int (FGFDMExec::*iPMF)(void) const;
+  instance->Tie("simulation/do_trim", this, (iPMF)0, &FGFDMExec::DoTrim);
+  Constructing = false;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 FGFDMExec::~FGFDMExec()
 {
+  instance->Untie("simulation/do_trim");
+
   try {
     DeAllocate();
     checkTied( instance );
+    if (Root == 0)  delete master;
   } catch ( string msg ) {
     cout << "Caught error: " << msg << endl;
   }
@@ -200,14 +205,14 @@ bool FGFDMExec::Allocate(void)
   Inertial        = new FGInertial(this);
   GroundReactions = new FGGroundReactions(this);
   Aircraft        = new FGAircraft(this);
-  GroundCallback  = new FGGroundCallback();
   Propagate       = new FGPropagate(this);
   Auxiliary       = new FGAuxiliary(this);
-  Output          = new FGOutput(this);
+  Input           = new FGInput(this);
 
-  State        = new FGState(this); // This must be done here, as the FGState
-                                    // class needs valid pointers to the above
-                                    // model classes
+  GroundCallback  = new FGGroundCallback();
+  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
 
@@ -237,23 +242,23 @@ bool FGFDMExec::Allocate(void)
     Error+=128;}
   if (!Propagate->InitModel())   {
     cerr << fgred << "Propagate model init failed" << fgdef << endl;
-    Error+=512;}
+    Error+=256;}
   if (!Auxiliary->InitModel())  {
     cerr << fgred << "Auxiliary model init failed" << fgdef << endl;
-    Error+=2058;}
-  if (!Output->InitModel())     {
-    cerr << fgred << "Output model init failed" << fgdef << endl;
-    Error+=4096;}
+    Error+=512;}
+  if (!Input->InitModel())  {
+    cerr << fgred << "Input model init failed" << fgdef << endl;
+    Error+=1024;}
 
   if (Error > 0) result = false;
 
   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.
-  // IC and Trim objects are NOT scheduled.
+  // instance, the atmosphere model could get executed every fifth pass it is called
+  // by the executive. IC and Trim objects are NOT scheduled.
 
+  Schedule(Input,           1);
   Schedule(Atmosphere,      1);
   Schedule(FCS,             1);
   Schedule(Propulsion,      1);
@@ -264,7 +269,6 @@ bool FGFDMExec::Allocate(void)
   Schedule(Aircraft,        1);
   Schedule(Propagate,       1);
   Schedule(Auxiliary,       1);
-  Schedule(Output,          1);
 
   modelLoaded = false;
 
@@ -275,6 +279,7 @@ bool FGFDMExec::Allocate(void)
 
 bool FGFDMExec::DeAllocate(void)
 {
+  delete Input;
   delete Atmosphere;
   delete FCS;
   delete Propulsion;
@@ -285,9 +290,14 @@ bool FGFDMExec::DeAllocate(void)
   delete Aircraft;
   delete Propagate;
   delete Auxiliary;
-  delete Output;
   delete State;
 
+  for (int i=0; i<Outputs.size(); i++) {
+    if (Outputs[i]) delete Outputs[i];
+  }
+
+  Outputs.clear();
+
   delete IC;
   delete Trim;
 
@@ -297,6 +307,7 @@ bool FGFDMExec::DeAllocate(void)
   Error       = 0;
 
   State           = 0;
+  Input           = 0;
   Atmosphere      = 0;
   FCS             = 0;
   Propulsion      = 0;
@@ -307,7 +318,6 @@ bool FGFDMExec::DeAllocate(void)
   Aircraft        = 0;
   Propagate       = 0;
   Auxiliary       = 0;
-  Output          = 0;
 
   modelLoaded = false;
   return modelLoaded;
@@ -346,8 +356,6 @@ bool FGFDMExec::Run(void)
 {
   FGModel* model_iterator;
 
-  if (frozen) return true;
-
   model_iterator = FirstModel;
   if (model_iterator == 0L) return false;
 
@@ -364,27 +372,29 @@ bool FGFDMExec::Run(void)
   }
 
   frame = Frame++;
-  State->IncrTime();
+  if (!Holding()) State->IncrTime();
   return true;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// This call will cause the sim time to reset to 0.0
 
 bool FGFDMExec::RunIC(void)
 {
-  State->Suspend();
+  State->SuspendIntegration();
   State->Initialize(IC);
   Run();
-  State->Resume();
+  State->ResumeIntegration();
 
   return true;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGFDMExec::SetGroundCallback(FGGroundCallback* p) {
-  if (GroundCallback)
-    delete GroundCallback;
+void FGFDMExec::SetGroundCallback(FGGroundCallback* p)
+{
+  if (GroundCallback) delete GroundCallback;
+
   GroundCallback = p;
 }
 
@@ -408,7 +418,6 @@ vector <string> FGFDMExec::EnumerateFDMs(void)
 bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model,
                 bool addModelToPath)
 {
-
   FGFDMExec::AircraftPath = AircraftPath;
   FGFDMExec::EnginePath = EnginePath;
 
@@ -417,13 +426,15 @@ bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model,
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-
 bool FGFDMExec::LoadModel(string model, bool addModelToPath)
 {
-  
-  bool result = true;
   string token;
   string aircraftCfgFileName;
+  string separator = "/";
+
+# ifdef macintosh
+    separator = ";";
+# endif
 
   if( AircraftPath.empty() || EnginePath.empty() ) {
     cerr << "Error: attempted to load aircraft with undefined ";
@@ -432,16 +443,16 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
   }
 
   aircraftCfgFileName = AircraftPath;
-# ifndef macintosh
-  if (addModelToPath) aircraftCfgFileName += "/" + model;
-  aircraftCfgFileName += "/" + model + ".xml";
-# else
-  if (addModelToPath) aircraftCfgFileName += ";"  + model;
-  aircraftCfgFileName += ";"  + model + ".xml";
-# endif
+  if (addModelToPath) aircraftCfgFileName += separator + model;
+  aircraftCfgFileName += separator + model + ".xml";
 
-  FGConfigFile AC_cfg(aircraftCfgFileName);
-  if (!AC_cfg.IsOpen()) return false;
+  FGXMLParse *XMLParse = new FGXMLParse();
+  Element* element = 0L;
+  Element* document;
+
+  ifstream input_file(aircraftCfgFileName.c_str());
+  readXML(input_file, *XMLParse);
+  document = XMLParse->GetDocument();
 
   modelName = model;
 
@@ -450,36 +461,35 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
     Allocate();
   }
 
-  if (!ReadPrologue(&AC_cfg)) return false;
-
-  while ((AC_cfg.GetNextConfigLine() != string("EOF")) &&
-         (token = AC_cfg.GetValue()) != string("/FDM_CONFIG")) {
-    if (token == "METRICS") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Metrics" << fgdef << endl;
-      if (!ReadMetrics(&AC_cfg)) result = false;
-    } else if (token == "SLAVE") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Slave flight vehicle: " << fgdef
-                                        << AC_cfg.GetValue("NAME") << endl;
-      if (!ReadSlave(&AC_cfg)) result = false;
-    } else if (token == "AERODYNAMICS") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Aerodynamics" << fgdef << endl;
-      if (!ReadAerodynamics(&AC_cfg)) result = false;
-    } else if (token == "UNDERCARRIAGE") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Landing Gear" << fgdef << endl;
-      if (!ReadUndercarriage(&AC_cfg)) result = false;
-    } else if (token == "PROPULSION") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Propulsion" << fgdef << endl;
-      if (!ReadPropulsion(&AC_cfg)) result = false;
-    } else if (token == "FLIGHT_CONTROL") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Flight Control" << fgdef << endl;
-      if (!ReadFlightControls(&AC_cfg)) result = false;
-    } else if (token == "AUTOPILOT") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Autopilot" << fgdef << endl;
-      if (!ReadFlightControls(&AC_cfg)) result = false;
-    } else if (token == "OUTPUT") {
-      if (debug_lvl > 0) cout << fgcyan << "\n  Reading Output directives" << fgdef << endl;
-      if (!ReadOutput(&AC_cfg)) result = false;
+  ReadPrologue(document);
+  element = document->GetElement();
+
+  bool result = true;
+  while (element && result) {
+    string element_name = element->GetName();
+    if (element_name == "fileheader" )           result = ReadFileHeader(element);
+    else if (element_name == "slave")            result = ReadSlave(element);
+    else if (element_name == "metrics")          result = Aircraft->Load(element);
+    else if (element_name == "mass_balance")     result = MassBalance->Load(element);
+    else if (element_name == "ground_reactions") result = GroundReactions->Load(element);
+    else if (element_name == "propulsion")       result = Propulsion->Load(element);
+    else if (element_name == "autopilot")        result = FCS->Load(element);
+    else if (element_name == "flight_control")   result = FCS->Load(element);
+    else if (element_name == "aerodynamics")     result = Aerodynamics->Load(element);
+    else if (element_name == "input")            result = Input->Load(element);
+    else if (element_name == "output")           {
+        FGOutput* Output = new FGOutput(this);
+        Output->InitModel();
+        Schedule(Output,       1);
+        Outputs.push_back(Output);
+        result = Output->Load(element);
+    }
+    else {
+      cerr << "Found unexpected subsystem: " << element_name << ", exiting." << endl;
+      result = false;
+      break;
     }
+    element = document->GetNextElement();
   }
 
   if (result) {
@@ -487,32 +497,93 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
     Debug(3);
   } else {
     cerr << fgred
-         << "  FGFDMExec: Failed to load aircraft and/or engine model"
+         << "  JSBSim failed to load aircraft and/or engine model"
          << fgdef << endl;
+    return false;
+  }
+
+  struct PropertyCatalogStructure masterPCS;
+  masterPCS.base_string = "";
+  masterPCS.node = (FGPropertyManager*)master;
+
+  BuildPropertyCatalog(&masterPCS);
+
+  return result;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
+{
+  struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure;
+  int node_idx = 0;
+  char int_buf[10];
+
+  for (int i=0; i<pcs->node->nChildren(); i++) {
+    pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
+    node_idx = pcs->node->getChild(i)->getIndex();
+    sprintf(int_buf, "[%d]", node_idx);
+    if (node_idx != 0) pcsNew->base_string += string(int_buf);
+    if (pcs->node->getChild(i)->nChildren() == 0) {
+      PropertyCatalog.push_back(pcsNew->base_string);
+    } else {
+      pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
+      BuildPropertyCatalog(pcsNew);
+    }
   }
+  delete pcsNew;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGFDMExec::QueryPropertyCatalog(string in)
+{
+  string results="";
+  for (int i=0; i<PropertyCatalog.size(); i++) {
+    if (PropertyCatalog[i].find(in) != string::npos) results += PropertyCatalog[i] + "\n";
+  }
+  if (results.empty()) return "No matches found\n";
+  return results;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGFDMExec::ReadFileHeader(Element* el)
+{
+  bool result = true; // true for success
+
+  if (debug_lvl & ~1) return result;
+
+  if (el->FindElement("author"))
+    cout << "  Model Author:  " << el->FindElement("author")->GetDataLine() << endl;
+  if (el->FindElement("filecreationdate"))
+    cout << "  Creation Date: " << el->FindElement("filecreationdate")->GetDataLine() << endl;
+  if (el->FindElement("version"))
+    cout << "  Version:       " << el->FindElement("version")->GetDataLine() << endl;
+  if (el->FindElement("description"))
+    cout << "  Description:   " << el->FindElement("description")->GetDataLine() << endl;
 
   return result;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::ReadPrologue(FGConfigFile* AC_cfg)
+bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document element
 {
-  string token = AC_cfg->GetValue();
-  string scratch;
-  string AircraftName;
+  bool result = true; // true for success
+
+  if (!el) return false;
 
-  AircraftName = AC_cfg->GetValue("NAME");
+  string AircraftName = el->GetAttributeValue("name");
   Aircraft->SetAircraftName(AircraftName);
 
-  if (debug_lvl > 0) cout << underon << "Reading Aircraft Configuration File"
+  if (debug_lvl & 1) cout << underon << "Reading Aircraft Configuration File"
             << underoff << ": " << highint << AircraftName << normint << endl;
-  scratch = AC_cfg->GetValue("VERSION").c_str();
 
-  CFGVersion = AC_cfg->GetValue("VERSION");
-  Release    = AC_cfg->GetValue("RELEASE");
+  CFGVersion = el->GetAttributeValue("version");
+  Release    = el->GetAttributeValue("release");
 
-  if (debug_lvl > 0)
+  if (debug_lvl & 1)
     cout << "                            Version: " << highint << CFGVersion
                                                     << normint << endl;
   if (CFGVersion != needed_cfg_version) {
@@ -523,10 +594,7 @@ bool FGFDMExec::ReadPrologue(FGConfigFile* AC_cfg)
     return false;
   }
 
-  if (Release == "ALPHA" && debug_lvl > 0) {
-#ifndef _MSC_VER
-    system("banner ALPHA");
-#endif
+  if (Release == "ALPHA" && (debug_lvl & 1)) {
     cout << endl << endl
          << highint << "This aircraft model is an " << fgred << Release
          << reset << highint << " release!!!" << endl << endl << reset
@@ -534,24 +602,33 @@ bool FGFDMExec::ReadPrologue(FGConfigFile* AC_cfg)
          << " will not fly as expected." << endl << endl
          << fgred << highint << "Use this model for development purposes ONLY!!!"
          << normint << reset << endl << endl;
-  } else if (Release == "BETA" && debug_lvl > 0) {
-#ifndef _MSC_VER
-    system("banner BETA");
-#endif
+  } else if (Release == "BETA" && (debug_lvl & 1)) {
     cout << endl << endl
          << highint << "This aircraft model is a " << fgred << Release
          << reset << highint << " release!!!" << endl << endl << reset
          << "This aircraft model probably will not fly as expected." << endl << endl
          << fgblue << highint << "Use this model for development purposes ONLY!!!"
          << normint << reset << endl << endl;
+  } else if (Release == "PRODUCTION" && (debug_lvl & 1)) {
+    cout << endl << endl
+         << highint << "This aircraft model is a " << fgblue << Release
+         << reset << highint << " release." << endl << endl << reset;
+  } else if (debug_lvl & 1) {
+    cout << endl << endl
+         << highint << "This aircraft model is an " << fgred << Release
+         << reset << highint << " release!!!" << endl << endl << reset
+         << "This aircraft model may not even properly load, and probably"
+         << " will not fly as expected." << endl << endl
+         << fgred << highint << "Use this model for development purposes ONLY!!!"
+         << normint << reset << endl << endl;
   }
 
-  return true;
+  return result;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
+bool FGFDMExec::ReadSlave(Element* el)
 {
   // Add a new slaveData object to the slave FDM list
   // Populate that slaveData element with a new FDMExec object
@@ -567,8 +644,8 @@ bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
   SlaveFDMList.push_back(new slaveData);
   SlaveFDMList.back()->exec = new FGFDMExec();
   SlaveFDMList.back()->exec->SetSlave();
-
-  string AircraftName = AC_cfg->GetValue("FILE");
+/*
+  string AircraftName = AC_cfg->GetValue("file");
 
   debug_lvl = 0;                 // turn off debug output for slave vehicle
 
@@ -580,15 +657,15 @@ bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
   AC_cfg->GetNextConfigLine();
   while ((token = AC_cfg->GetValue()) != string("/SLAVE")) {
     *AC_cfg >> token;
-    if      (token == "XLOC")  { *AC_cfg >> SlaveFDMList.back()->x;    }
-    else if (token == "YLOC")  { *AC_cfg >> SlaveFDMList.back()->y;    }
-    else if (token == "ZLOC")  { *AC_cfg >> SlaveFDMList.back()->z;    }
-    else if (token == "PITCH") { *AC_cfg >> SlaveFDMList.back()->pitch;}
-    else if (token == "YAW")   { *AC_cfg >> SlaveFDMList.back()->yaw;  }
-    else if (token == "ROLL")  { *AC_cfg >> SlaveFDMList.back()->roll;  }
+    if      (token == "xloc")  { *AC_cfg >> SlaveFDMList.back()->x;    }
+    else if (token == "yloc")  { *AC_cfg >> SlaveFDMList.back()->y;    }
+    else if (token == "zloc")  { *AC_cfg >> SlaveFDMList.back()->z;    }
+    else if (token == "pitch") { *AC_cfg >> SlaveFDMList.back()->pitch;}
+    else if (token == "yaw")   { *AC_cfg >> SlaveFDMList.back()->yaw;  }
+    else if (token == "roll")  { *AC_cfg >> SlaveFDMList.back()->roll;  }
     else cerr << "Unknown identifier: " << token << " in slave vehicle definition" << endl;
   }
-
+*/
   if (debug_lvl > 0)  {
     cout << "      X = " << SlaveFDMList.back()->x << endl;
     cout << "      Y = " << SlaveFDMList.back()->y << endl;
@@ -603,82 +680,85 @@ bool FGFDMExec::ReadSlave(FGConfigFile* AC_cfg)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::ReadPropulsion(FGConfigFile* AC_cfg)
+FGPropertyManager* FGFDMExec::GetPropertyManager(void)
 {
-  if (!Propulsion->Load(AC_cfg)) {
-    cerr << "  Propulsion not successfully loaded" << endl;
-    return false;
-  }
-  return true;
+  return instance;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::ReadFlightControls(FGConfigFile* AC_cfg)
+FGTrim* FGFDMExec::GetTrim(void)
 {
-  if (!FCS->Load(AC_cfg)) {
-    cerr << "  Flight Controls not successfully loaded" << endl;
-    return false;
-  }
-  return true;
+  delete Trim;
+  Trim = new FGTrim(this,tNone);
+  return Trim;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::ReadAerodynamics(FGConfigFile* AC_cfg)
+void FGFDMExec::DisableOutput(void)
 {
-  if (!Aerodynamics->Load(AC_cfg)) {
-    cerr << "  Aerodynamics not successfully loaded" << endl;
-    return false;
+  for (int i=0; i<Outputs.size(); i++) {
+    Outputs[i]->Disable();
   }
-  return true;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::ReadUndercarriage(FGConfigFile* AC_cfg)
+void FGFDMExec::EnableOutput(void)
 {
-  if (!GroundReactions->Load(AC_cfg)) {
-    cerr << "  Ground Reactions not successfully loaded" << endl;
-    return false;
+  for (int i=0; i<Outputs.size(); i++) {
+    Outputs[i]->Enable();
   }
-  return true;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::ReadMetrics(FGConfigFile* AC_cfg)
+void FGFDMExec::DoTrim(int mode)
 {
-  if (!Aircraft->Load(AC_cfg)) {
-    cerr << "  Aircraft metrics not successfully loaded" << endl;
-    return false;
-  }
-  return true;
-}
+  double saved_time;
 
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+cout << "DoTrim called" << endl;
 
-bool FGFDMExec::ReadOutput(FGConfigFile* AC_cfg)
-{
-  if (!Output->Load(AC_cfg)) {
-    cerr << "  Output not successfully loaded" << endl;
-    return false;
+  if (Constructing) return;
+
+  if (mode < 0 || mode > JSBSim::tNone) {
+    cerr << endl << "Illegal trimming mode!" << endl << endl;
+    return;
   }
-  return true;
+  saved_time = State->Getsim_time();
+  FGTrim trim(this, (JSBSim::TrimMode)mode);
+  if ( !trim.DoTrim() ) cerr << endl << "Trim Failed" << endl << endl;
+  trim.Report();
+  State->Setsim_time(saved_time);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGPropertyManager* FGFDMExec::GetPropertyManager(void) {
-  return instance;
+void FGFDMExec::UseAtmosphereMSIS(void)
+{
+  FGAtmosphere *oldAtmosphere = Atmosphere;
+  Atmosphere = new MSIS(this);
+  if (!Atmosphere->InitModel()) {
+    cerr << fgred << "MSIS Atmosphere model init failed" << fgdef << endl;
+    Error+=1;
+  }
+  delete oldAtmosphere;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGTrim* FGFDMExec::GetTrim(void) {
-  delete Trim;
-  Trim = new FGTrim(this,tNone);
-  return Trim;
+void FGFDMExec::UseAtmosphereMars(void)
+{
+/*
+  FGAtmosphere *oldAtmosphere = Atmosphere;
+  Atmosphere = new FGMars(this);
+  if (!Atmosphere->InitModel()) {
+    cerr << fgred << "Mars Atmosphere model init failed" << fgdef << endl;
+    Error+=1;
+  }
+  delete oldAtmosphere;
+*/
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -721,7 +801,7 @@ void FGFDMExec::Debug(int from)
   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
     if (from == 2) {
       cout << "================== Frame: " << Frame << "  Time: "
-           << State->Getsim_time() << endl;
+           << State->Getsim_time() << " dt: " << State->Getdt() << endl;
     }
   }
   if (debug_lvl & 8 ) { // Runtime state variables
@@ -737,3 +817,4 @@ void FGFDMExec::Debug(int from)
 }
 }
 
+
index ae9edb9999029b245b3a1bff7670d05c11fa6708..e440ab76365818fee8c3cf87f0d86936eae1a531 100644 (file)
@@ -40,13 +40,16 @@ SENTRY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include "FGModel.h"
-#include "FGTrim.h"
-#include "FGInitialCondition.h"
-#include "FGJSBBase.h"
-#include "FGGroundCallback.h"
-#include "FGPropertyManager.h"
-#include "FGPropagate.h"
+#include <models/FGModel.h>
+#include <models/FGOutput.h>
+#include <models/FGInput.h>
+#include <initialization/FGTrim.h>
+#include <initialization/FGInitialCondition.h>
+#include <FGJSBBase.h>
+#include <input_output/FGPropertyManager.h>
+#include <input_output/FGXMLParse.h>
+#include <input_output/FGGroundCallback.h>
+#include <models/FGPropagate.h>
 
 #include <vector>
 
@@ -74,8 +77,7 @@ 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
-    "Load()" method of that system is called (e.g. LoadFCS).
+    corresponding Load() method is called (e.g. LoadFCS).
 
     <h4>JSBSim Debugging Directives</h4>
 
@@ -134,17 +136,12 @@ public:
 
   /** Initializes the sim from the initial condition object and executes
       each scheduled model without integrating i.e. dt=0.
-      @return true if successful
-       */
+      @return true if successful */
   bool RunIC(void);
 
-  /// Freezes the sim
-  void Freeze(void) {frozen = true;}
-
-  /// Resumes the sim
-  void Resume(void) {frozen = false;}
-
-  void SetGroundCallback(FGGroundCallback*);
+  /** Sets the ground callback pointer.
+      @param gc A pointer to a ground callback object.  */
+  void SetGroundCallback(FGGroundCallback* gc);
 
   /** Loads an aircraft model.
       @param AircraftPath path to the aircraft directory. For instance:
@@ -162,7 +159,6 @@ public:
   bool LoadModel(string AircraftPath, string EnginePath, string model,
                  bool addModelToPath = true);
 
-
   /** Loads an aircraft model.  The paths to the aircraft and engine
       config file directories must be set prior to calling this.  See
       below.
@@ -175,37 +171,23 @@ public:
       @return true if successful*/
   bool LoadModel(string model, bool addModelToPath = true);
 
-
   /** Sets the path to the engine config file directories.
       @param path path to the directory under which engine config
-      files are kept, for instance "engine"
-  */
+      files are kept, for instance "engine"  */
   bool SetEnginePath(string path)   { EnginePath = path; return true; }
 
   /** Sets the path to the aircraft config file directories.
       @param path path to the aircraft directory. For instance:
       "aircraft". Under aircraft, then, would be directories for various
-      modeled aircraft such as C172/, x15/, etc.
-  */
+      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; }
-
-
   /// @name Top-level executive State and Model retrieval mechanism
   //@{
-  /// Returns the FGState pointer.
-  inline FGState* GetState(void)              {return State;}
   /// Returns the FGAtmosphere pointer.
   inline FGAtmosphere* GetAtmosphere(void)    {return Atmosphere;}
   /// Returns the FGFCS pointer.
   inline FGFCS* GetFCS(void)                  {return FCS;}
-  /// Returns the FGGroundCallback pointer.
-  inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;}
   /// Returns the FGPropulsion pointer.
   inline FGPropulsion* GetPropulsion(void)    {return Propulsion;}
   /// Returns the FGAircraft pointer.
@@ -222,41 +204,100 @@ public:
   inline FGPropagate* GetPropagate(void)      {return Propagate;}
   /// Returns the FGAuxiliary pointer.
   inline FGAuxiliary* GetAuxiliary(void)      {return Auxiliary;}
-  /// Returns the FGOutput pointer.
-  inline FGOutput* GetOutput(void)            {return Output;}
+  /// Returns the FGInput pointer.
+  inline FGInput* GetInput(void)              {return Input;}
+  /// Returns the FGGroundCallback pointer.
+  inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;}
+  /// Returns the FGState pointer.
+  inline FGState* GetState(void)              {return State;}
   // Returns a pointer to the FGInitialCondition object
   inline FGInitialCondition* GetIC(void)      {return IC;}
   // Returns a pointer to the FGTrim object
-  FGTrim* GetTrim(void);
+  inline 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;}
 
+  /// Returns the model name.
   string GetModelName(void) { return modelName; }
 
+  /// Returns a pointer to the property manager object.
   FGPropertyManager* GetPropertyManager(void);
+  /// Returns a vector of strings representing the names of all loaded models (future)
   vector <string> EnumerateFDMs(void);
+  /// Marks this instance of the Exec object as a "slave" object.
   void SetSlave(void) {IsSlave = true;}
 
+  /** Executes trimming in the selected mode.
+  *   @param mode Specifies how to trim:
+  * - tLongitudinal=0
+  * - tFull
+  * - tGround
+  * - tPullup
+  * - tCustom
+  * - tTurn
+  * - tNone
+  */
+  void DoTrim(int mode);
+
+  /// Disables data logging to all outputs.
+  void DisableOutput(void);
+  /// Enables data logging to all outputs.
+  void EnableOutput(void);
+  /// Pauses execution by preventing time from incrementing.
+  void Hold(void) {holding = true;}
+  /// Resumes execution from a "Hold".
+  void Resume(void) {holding = false;}
+  /// Returns true if the simulation is Holding (i.e. simulation time is not moving).
+  bool Holding(void) {return holding;}
+
+  struct PropertyCatalogStructure {
+    /// Name of the property.
+    string base_string;
+    /// The node for the property.
+    FGPropertyManager *node;
+  };
+
+  /** Builds a catalog of properties.
+  *   This function descends the property tree and creates a list (an STL vector)
+  *   containing the name and node for all properties.
+  *   @param pcs The "root" property catalog structure pointer.  */
+  void BuildPropertyCatalog(struct PropertyCatalogStructure* pcs);
+
+  /** Retrieves property or properties matching the supplied string.
+  *   A string is returned that contains a carriage return delimited list of all
+  *   strings in the property catalog that matches the supplied chack string.
+  *   @param check The string to search for in the property catalog.
+  *   @return the carriage-return-delimited string containing all matching strings
+  *               in the catalog.  */
+  string QueryPropertyCatalog(string check);
+
+  /// Use the MSIS atmosphere model.
+  void UseAtmosphereMSIS(void);
+
+  /// Use the Mars atmosphere model. (Not operative yet.)
+  void UseAtmosphereMars(void); 
+
 private:
   FGModel* FirstModel;
 
-  bool frozen;
   bool terminate;
+  bool holding;
+  bool Constructing;
   int  Error;
   unsigned int Frame;
   unsigned int IdFDM;
+  FGPropertyManager* Root;
   static unsigned int FDMctr;
   bool modelLoaded;
   string modelName;
   bool IsSlave;
   static FGPropertyManager *master;
   FGPropertyManager *instance;
+  vector <string> PropertyCatalog;
 
   struct slaveData {
     FGFDMExec* exec;
@@ -279,15 +320,14 @@ private:
 
   string AircraftPath;
   string EnginePath;
-//  string ControlPath;
 
   string CFGVersion;
   string Release;
 
+  FGGroundCallback*  GroundCallback;
   FGState*           State;
   FGAtmosphere*      Atmosphere;
   FGFCS*             FCS;
-  FGGroundCallback*  GroundCallback;
   FGPropulsion*      Propulsion;
   FGMassBalance*     MassBalance;
   FGAerodynamics*    Aerodynamics;
@@ -296,21 +336,17 @@ private:
   FGAircraft*        Aircraft;
   FGPropagate*       Propagate;
   FGAuxiliary*       Auxiliary;
-  FGOutput*          Output;
+  FGInput*           Input;
+  vector <FGOutput*> Outputs;
 
   FGInitialCondition* IC;
   FGTrim *Trim;
 
   vector <slaveData*> SlaveFDMList;
 
-  bool ReadMetrics(FGConfigFile*);
-  bool ReadSlave(FGConfigFile*);
-  bool ReadPropulsion(FGConfigFile*);
-  bool ReadFlightControls(FGConfigFile*);
-  bool ReadAerodynamics(FGConfigFile*);
-  bool ReadUndercarriage(FGConfigFile*);
-  bool ReadPrologue(FGConfigFile*);
-  bool ReadOutput(FGConfigFile*);
+  bool ReadFileHeader(Element*);
+  bool ReadSlave(Element*);
+  bool ReadPrologue(Element*);
 
   bool Allocate(void);
   bool DeAllocate(void);
index 61669d17967cc3460cfce393f9c5ad3588a8da9a..c6fcc0f6caad39b0b7e7a9c276963bc2bc27dad9 100644 (file)
@@ -76,6 +76,7 @@ const double FGJSBBase::radtodeg = 57.29578;
 const double FGJSBBase::degtorad = 1.745329E-2;
 const double FGJSBBase::hptoftlbssec = 550.0;
 const double FGJSBBase::psftoinhg = 0.014138;
+const double FGJSBBase::psftopa = 47.88;
 const double FGJSBBase::fpstokts = 0.592484;
 const double FGJSBBase::ktstofps = 1.68781;
 const double FGJSBBase::inchtoft = 0.08333333;
@@ -92,8 +93,8 @@ 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.65";
-const string FGJSBBase::JSBSim_version = "0.9.5";
+const string FGJSBBase::needed_cfg_version = "2.0";
+const string FGJSBBase::JSBSim_version = "0.9.10.111805";
 
 std::queue <FGJSBBase::Message*> FGJSBBase::Messages;
 FGJSBBase::Message FGJSBBase::localMsg;
index 7b75f84c6587972dbf234cff6c3f90046b49f5a3..f47a779f693128bdfca0362cd9abbfa2c670f4b3 100644 (file)
@@ -42,18 +42,18 @@ INCLUDES
 
 #ifdef FGFS
 #  include <simgear/compiler.h>
-#  include <simgear/constants.h>
 #  include <math.h>
 #  include <queue>
 #  include STL_STRING
 
 SG_USING_STD(string);
 
-# ifndef M_PI
-#  define M_PI SG_PI
-# endif
+#  ifndef M_PI
+#    include <simgear/constants.h>
+#    define M_PI SG_PI
+#  endif
 
-#else
+#else  // JSBSim section
 
 #  include <queue>
 #  include <string>
@@ -65,13 +65,27 @@ SG_USING_STD(string);
 
 using std::string;
 
-# ifndef M_PI
-#  define M_PI 3.14159265358979323846
-# endif
+#  if defined(_MSC_VER) && _MSC_VER <= 1200
+#    ifndef max
+#      define max(a,b)            (((a) > (b)) ? (a) : (b))
+#    endif
+
+#    ifndef min
+#      define min(a,b)            (((a) < (b)) ? (a) : (b))
+#    endif
+#  else
+
+using std::fabs;
+
+#  endif
+
+#  ifndef M_PI
+#    define M_PI 3.14159265358979323846
+#  endif
 
 #endif
 
-#if !defined(WIN32) || defined(__GNUC__) || ( defined(_MSC_VER) && (_MSC_VER >= 1400)) 
+#if !defined(WIN32) || defined(__GNUC__)
 using std::max;
 #endif
 
@@ -92,6 +106,8 @@ CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 /** JSBSim Base class.
+*   This class provides universal constants, utility functions, messaging
+*   functions, and enumerated constants to JSBSim.
     @author Jon S. Berndt
     @version $Id$
 */
@@ -178,23 +194,40 @@ public:
       @return pointer to a Message structure (or NULL if no mesage) */
   Message* ProcessMessage(void);
   //@}
+
+  /** Returns the version number of JSBSim.
+  *   @return The version number of JSBSim. */
   string GetVersion(void) {return JSBSim_version;}
 
+  /// Disables highlighting in the console output.
   void disableHighLighting(void);
 
   static short debug_lvl;
+
+  /** Converts from degrees Kelvin to degrees Fahrenheit.
+  *   @param kelvin The temperature in degrees Kelvin.
+  *   @return The temperature in Fahrenheit. */
   static double KelvinToFahrenheit (double kelvin) {
     return 1.8*kelvin - 459.4;
   }
 
+  /** Converts from degrees Rankine to degrees Celsius.
+  *   @param rankine The temperature in degrees Rankine.
+  *   @return The temperature in Celsius. */
   static double RankineToCelsius (double rankine) {
     return (rankine - 491.67)/1.8;
   }
 
+  /** Converts from degrees Fahrenheit to degrees Celsius.
+  *   @param fahrenheit The temperature in degrees Fahrenheit.
+  *   @return The temperature in Celsius. */
   static double FahrenheitToCelsius (double fahrenheit) {
     return (fahrenheit - 32.0)/1.8;
   }
 
+  /** Converts from degrees Celsius to degrees Fahrenheit.
+  *   @param celsius The temperature in degrees Celsius.
+  *   @return The temperature in Fahrenheit. */
   static double CelsiusToFahrenheit (double celsius) {
     return celsius * 1.8 + 32.0;
   }
@@ -247,6 +280,7 @@ protected:
   static const double degtorad;
   static const double hptoftlbssec;
   static const double psftoinhg;
+  static const double psftopa;
   static const double fpstokts;
   static const double ktstofps;
   static const double inchtoft;
@@ -257,8 +291,8 @@ protected:
   static const double slugtolb;
   static const string needed_cfg_version;
   static const string JSBSim_version;
-};
 
+public:
 /// Moments L, M, N
 enum {eL     = 1, eM,     eN    };
 /// Rates P, Q, R
@@ -280,6 +314,8 @@ enum {eLat = 1, eLong, eRad     };
 /// Conversion specifiers
 enum {inNone = 0, inDegrees, inRadians, inMeters, inFeet };
 
+};
+
 }
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 #endif
diff --git a/src/FDM/JSBSim/FGLocation.h b/src/FDM/JSBSim/FGLocation.h
deleted file mode 100644 (file)
index d0c3eca..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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.
-
-    Note: The latitude is a GEOCENTRIC value. FlightGear
-    converts latitude to a geodetic value and uses that. In order to get best
-    matching relative to a map, geocentric latitude must be converted to geodetic.
-
-    @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.
-      @param lon longitude
-      @param lat GEOCENTRIC latitude
-      @param distance from center of earth to vehicle in feet*/
-  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
diff --git a/src/FDM/JSBSim/FGMassBalance.cpp b/src/FDM/JSBSim/FGMassBalance.cpp
deleted file mode 100644 (file)
index f925c8f..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGMassBalance.cpp
- Author:       Jon S. Berndt
- Date started: 09/12/2000
- Purpose:      This module models weight and balance
-
- ------------- Copyright (C) 2000  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 models the change in weight and balance of the aircraft due to fuel
-burnoff, etc.
-
-HISTORY
---------------------------------------------------------------------------------
-09/12/2000  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGMassBalance.h"
-#include "FGPropulsion.h"
-#include "FGPropertyManager.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_MASSBALANCE;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex)
-{
-  Name = "FGMassBalance";
-  Weight = EmptyWeight = Mass = 0.0;
-
-  vbaseXYZcg.InitMatrix(0.0);
-  baseJ.InitMatrix();
-  mJ.InitMatrix();
-  mJinv.InitMatrix();
-  pmJ.InitMatrix();
-
-  bind();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMassBalance::~FGMassBalance()
-{
-  unbind();
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGMassBalance::Run(void)
-{
-  double denom, k1, k2, k3, k4, k5, k6;
-  double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
-
-  if (!FGModel::Run()) {
-
-    Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetPointMassWeight();
-
-    Mass = lbtoslug*Weight;
-
-// Calculate new CG
-
-    vXYZcg = (Propulsion->GetTanksMoment() + EmptyWeight*vbaseXYZcg
-                                       + GetPointMassMoment() ) / Weight;
-
-// Calculate new total moments of inertia
-
-    // At first it is the base configuration inertia matrix ...
-    mJ = baseJ;
-    // ... with the additional term originating from the parallel axis theorem.
-    mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
-    // Then add the contributions from the additional pointmasses.
-    mJ += CalculatePMInertias();
-    mJ += Propulsion->CalculateTankInertias();
-
-    Ixx = mJ(1,1);
-    Iyy = mJ(2,2);
-    Izz = mJ(3,3);
-    Ixy = -mJ(1,2);
-    Ixz = -mJ(1,3);
-    Iyz = -mJ(2,3);
-
-// Calculate inertia matrix inverse (ref. Stevens and Lewis, "Flight Control & Simulation")
-
-    k1 = (Iyy*Izz - Iyz*Iyz);
-    k2 = (Iyz*Ixz + Ixy*Izz);
-    k3 = (Ixy*Iyz + Iyy*Ixz);
-
-    denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 );
-    k1 = k1*denom;
-    k2 = k2*denom;
-    k3 = k3*denom;
-    k4 = (Izz*Ixx - Ixz*Ixz)*denom;
-    k5 = (Ixy*Ixz + Iyz*Ixx)*denom;
-    k6 = (Ixx*Iyy - Ixy*Ixy)*denom;
-
-    mJinv.InitMatrix( k1, k2, k3,
-                      k2, k4, k5,
-                      k3, k5, k6 );
-
-    Debug(2);
-
-    return false;
-  } else {
-    return true;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGMassBalance::AddPointMass(double weight, double X, double Y, double Z)
-{
-  PointMassLoc.push_back(FGColumnVector3(X, Y, Z));
-  PointMassWeight.push_back(weight);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGMassBalance::GetPointMassWeight(void)
-{
-  double PM_total_weight = 0.0;
-
-  for (unsigned int i=0; i<PointMassWeight.size(); i++) {
-    PM_total_weight += PointMassWeight[i];
-  }
-  return PM_total_weight;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
-{
-  PointMassCG.InitMatrix();
-
-  for (unsigned int i=0; i<PointMassLoc.size(); i++) {
-    PointMassCG += PointMassWeight[i]*PointMassLoc[i];
-  }
-  return PointMassCG;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33& FGMassBalance::CalculatePMInertias(void)
-{
-  unsigned int size;
-
-  size = PointMassLoc.size();
-  if (size == 0) return pmJ;
-
-  pmJ = FGMatrix33();
-
-  for (unsigned int i=0; i<size; i++)
-    pmJ += GetPointmassInertia( lbtoslug * PointMassWeight[i], PointMassLoc[i] );
-
-  return pmJ;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector3 FGMassBalance::StructuralToBody(const FGColumnVector3& r) const
-{
-  // Under the assumption that in the structural frame the:
-  //
-  // - X-axis is directed afterwards,
-  // - Y-axis is directed towards the right,
-  // - Z-axis is directed upwards,
-  //
-  // (as documented in http://jsbsim.sourceforge.net/JSBSimCoordinates.pdf)
-  // we have to subtract first the center of gravity of the plane which
-  // is also defined in the structural frame:
-  //
-  //   FGColumnVector3 cgOff = r - vXYZcg;
-  //
-  // Next, we do a change of units:
-  //
-  //   cgOff *= inchtoft;
-  //
-  // And then a 180 degree rotation is done about the Y axis so that the:
-  //
-  // - X-axis is directed forward,
-  // - Y-axis is directed towards the right,
-  // - Z-axis is directed downward.
-  //
-  // This is needed because the structural and body frames are 180 degrees apart.
-
-  return FGColumnVector3(inchtoft*(vXYZcg(1)-r(1)),
-                         inchtoft*(r(2)-vXYZcg(2)),
-                         inchtoft*(vXYZcg(3)-r(3)));
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGMassBalance::bind(void)
-{
-  typedef double (FGMassBalance::*PMF)(int) const;
-  PropertyManager->Tie("inertia/mass-slugs", this,
-                       &FGMassBalance::GetMass);
-  PropertyManager->Tie("inertia/weight-lbs", this,
-                       &FGMassBalance::GetWeight);
-  PropertyManager->Tie("inertia/cg-x-ft", this,1,
-                       (PMF)&FGMassBalance::GetXYZcg);
-  PropertyManager->Tie("inertia/cg-y-ft", this,2,
-                       (PMF)&FGMassBalance::GetXYZcg);
-  PropertyManager->Tie("inertia/cg-z-ft", this,3,
-                       (PMF)&FGMassBalance::GetXYZcg);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGMassBalance::unbind(void)
-{
-  PropertyManager->Untie("inertia/mass-slugs");
-  PropertyManager->Untie("inertia/weight-lbs");
-  PropertyManager->Untie("inertia/cg-x-ft");
-  PropertyManager->Untie("inertia/cg-y-ft");
-  PropertyManager->Untie("inertia/cg-z-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 FGMassBalance::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: FGMassBalance" << endl;
-    if (from == 1) cout << "Destroyed:    FGMassBalance" << 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 (from == 2) {
-      if (EmptyWeight <= 0.0 || EmptyWeight > 1e9)
-        cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl;
-      if (Weight <= 0.0 || Weight > 1e9)
-        cout << "MassBalance::Weight out of bounds: " << Weight << endl;
-      if (Mass <= 0.0 || Mass > 1e9)
-        cout << "MassBalance::Mass out of bounds: " << Mass << endl;
-    }
-  }
-  if (debug_lvl & 64) {
-    if (from == 0) { // Constructor
-      cout << IdSrc << endl;
-      cout << IdHdr << endl;
-    }
-  }
-}
-}
diff --git a/src/FDM/JSBSim/FGMassBalance.h b/src/FDM/JSBSim/FGMassBalance.h
deleted file mode 100644 (file)
index 14c11f0..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGMassBalance.h
- Author:       Jon S. Berndt
- Date started: 09/12/2000
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-09/12/2000  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGMASSBALANCE_H
-#define FGMASSBALANCE_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGModel.h"
-#include "FGColumnVector3.h"
-#include "FGMatrix33.h"
-#include <vector>
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_MASSBALANCE "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONSS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models weight and balance information.
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGMassBalance : public FGModel
-{
-
-public:
-  FGMassBalance(FGFDMExec*);
-  ~FGMassBalance();
-
-  bool Run(void);
-
-  inline double GetMass(void) const {return Mass;}
-  inline double GetWeight(void) const {return Weight;}
-  inline double GetEmptyWeight(void) const {return EmptyWeight;}
-  inline FGColumnVector3& GetXYZcg(void) {return vXYZcg;}
-  inline double GetXYZcg(int axis) const  {return vXYZcg(axis);}
-  inline double GetbaseXYZcg(int axis) const  {return vbaseXYZcg(axis);}
-
-  /** Computes the inertia contribution of a pointmass.
-      Computes and returns the inertia matrix of a pointmass of mass
-      slugs at the given vector r in the structural frame. The units
-      should be for the mass in slug and the vector in the structural
-      frame as usual in inches.
-      @param slugs the mass of this single pointmass given in slugs
-      @param r the location of this single pointmass in the structural frame
-   */
-  FGMatrix33 GetPointmassInertia(double slugs, const FGColumnVector3& r) const
-  {
-    FGColumnVector3 v = StructuralToBody( r );
-    FGColumnVector3 sv = slugs*v;
-    double xx = sv(1)*v(1);
-    double yy = sv(2)*v(2);
-    double zz = sv(3)*v(3);
-    double xy = -sv(1)*v(2);
-    double xz = -sv(1)*v(3);
-    double yz = -sv(2)*v(3);
-    return FGMatrix33( yy+zz, xy, xz,
-                       xy, xx+zz, yz,
-                       xz, yz, xx+yy );
-  }
-
-  /** Conversion from the structural frame to the body frame.
-      Converts the location given in the structural frame
-      coordinate system to the body frame. The units of the structural
-      frame are assumed to be in inches. The unit of the result is in
-      ft.
-      @param r vector coordinate in the structural reference frame (X positive
-               aft, measurements in inches).
-      @return vector coordinate in the body frame, in feet.
-   */
-  FGColumnVector3 StructuralToBody(const FGColumnVector3& r) const;
-
-  inline void SetEmptyWeight(double EW) { EmptyWeight = EW;}
-  inline void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = vXYZcg = CG;}
-
-  void AddPointMass(double weight, double X, double Y, double Z);
-  double GetPointMassWeight(void);
-  FGColumnVector3& GetPointMassMoment(void);
-  FGMatrix33& GetJ(void) {return mJ;}
-  FGMatrix33& GetJinv(void) {return mJinv;}
-  void SetAircraftBaseInertias(FGMatrix33 BaseJ) {baseJ = BaseJ;}
-  FGMatrix33& GetAircraftBaseInertias(void) {return baseJ;}
-  int GetNumPointMasses(void) {return PointMassLoc.size();}
-  FGColumnVector3& GetPointMassLoc(int i) {return PointMassLoc[i];}
-  double GetPointMassWeight(int i) {return PointMassWeight[i];}
-  
-  void bind(void);
-  void unbind(void);
-
-private:
-  double Weight;
-  double EmptyWeight;
-  double Mass;
-  FGMatrix33 mJ;
-  FGMatrix33 mJinv;
-  FGMatrix33 pmJ;
-  FGMatrix33 baseJ;
-  FGColumnVector3 vXYZcg;
-  FGColumnVector3 vXYZtank;
-  FGColumnVector3 vbaseXYZcg;
-  FGColumnVector3 vPMxyz;
-  vector <FGColumnVector3> PointMassLoc;
-  vector <double> PointMassWeight;
-  FGColumnVector3 PointMassCG;
-  FGMatrix33& CalculatePMInertias(void);
-
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
diff --git a/src/FDM/JSBSim/FGMatrix33.cpp b/src/FDM/JSBSim/FGMatrix33.cpp
deleted file mode 100644 (file)
index 5027f4c..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Module: FGMatrix33.cpp
-Author: Tony Peden, Jon Berndt, Mathias Frolich
-Date started: 1998
-Purpose: FGMatrix33 class
-Called by: Various
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-
-HISTORY
---------------------------------------------------------------------------------
-??/??/??   TP   Created
-03/16/2000 JSB  Added exception throwing
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGMatrix33.h"
-#include "FGColumnVector3.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_MATRIX33;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33::FGMatrix33(void)
-{
-  data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
-    data[6] = data[7] = data[8] = 0.0;
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-ostream& operator<<(ostream& os, const FGMatrix33& M)
-{
-  for (unsigned int i=1; i<=M.Rows(); i++) {
-    for (unsigned int j=1; j<=M.Cols(); j++) {
-      if (i == M.Rows() && j == M.Cols())
-        os << M(i,j);
-      else
-        os << M(i,j) << ", ";
-    }
-  }
-  return os;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-istream& operator>>(istream& is, FGMatrix33& M)
-{
-  for (unsigned int i=1; i<=M.Rows(); i++) {
-    for (unsigned int j=1; j<=M.Cols(); j++) {
-      is >> M(i,j);
-    }
-  }
-  return is;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGMatrix33::Determinant(void) const {
-  return Entry(1,1)*Entry(2,2)*Entry(3,3) + Entry(1,2)*Entry(2,3)*Entry(3,1)
-    + Entry(1,3)*Entry(2,1)*Entry(3,2) - Entry(1,3)*Entry(2,2)*Entry(3,1)
-    - Entry(1,2)*Entry(2,1)*Entry(3,3) - Entry(2,3)*Entry(3,2)*Entry(1,1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33 FGMatrix33::Inverse(void) const {
-  // Compute the inverse of a general matrix using Cramers rule.
-  // I guess googling for cramers rule gives tons of references
-  // for this. :)
-  double rdet = 1.0/Determinant();
-
-  double i11 = rdet*(Entry(2,2)*Entry(3,3)-Entry(2,3)*Entry(3,2));
-  double i21 = rdet*(Entry(2,3)*Entry(3,1)-Entry(2,1)*Entry(3,3));
-  double i31 = rdet*(Entry(2,1)*Entry(3,2)-Entry(2,2)*Entry(3,1));
-  double i12 = rdet*(Entry(1,3)*Entry(3,2)-Entry(1,2)*Entry(3,3));
-  double i22 = rdet*(Entry(1,1)*Entry(3,3)-Entry(1,3)*Entry(3,1));
-  double i32 = rdet*(Entry(1,2)*Entry(3,1)-Entry(1,1)*Entry(3,2));
-  double i13 = rdet*(Entry(1,2)*Entry(2,3)-Entry(1,3)*Entry(2,2));
-  double i23 = rdet*(Entry(1,3)*Entry(2,1)-Entry(1,1)*Entry(2,3));
-  double i33 = rdet*(Entry(1,1)*Entry(2,2)-Entry(1,2)*Entry(2,1));
-
-  return FGMatrix33( i11, i12, i13,
-                     i21, i22, i23,
-                     i31, i32, i33 );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGMatrix33::InitMatrix(void)
-{
-  data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
-    data[6] = data[7] = data[8] = 0.0;
-}
-
-// *****************************************************************************
-// binary operators ************************************************************
-// *****************************************************************************
-
-FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const
-{
-  return FGMatrix33( Entry(1,1) - M(1,1),
-                     Entry(1,2) - M(1,2),
-                     Entry(1,3) - M(1,3),
-                     Entry(2,1) - M(2,1),
-                     Entry(2,2) - M(2,2),
-                     Entry(2,3) - M(2,3),
-                     Entry(3,1) - M(3,1),
-                     Entry(3,2) - M(3,2),
-                     Entry(3,3) - M(3,3) );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M)
-{
-  data[0] -= M.data[0];
-  data[1] -= M.data[1];
-  data[2] -= M.data[2];
-  data[3] -= M.data[3];
-  data[4] -= M.data[4];
-  data[5] -= M.data[5];
-  data[6] -= M.data[6];
-  data[7] -= M.data[7];
-  data[8] -= M.data[8];
-
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const
-{
-  return FGMatrix33( Entry(1,1) + M(1,1),
-                     Entry(1,2) + M(1,2),
-                     Entry(1,3) + M(1,3),
-                     Entry(2,1) + M(2,1),
-                     Entry(2,2) + M(2,2),
-                     Entry(2,3) + M(2,3),
-                     Entry(3,1) + M(3,1),
-                     Entry(3,2) + M(3,2),
-                     Entry(3,3) + M(3,3) );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)
-{
-  Entry(1,1) += M(1,1);
-  Entry(1,2) += M(1,2);
-  Entry(1,3) += M(1,3);
-  Entry(2,1) += M(2,1);
-  Entry(2,2) += M(2,2);
-  Entry(2,3) += M(2,3);
-  Entry(3,1) += M(3,1);
-  Entry(3,2) += M(3,2);
-  Entry(3,3) += M(3,3);
-
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33 FGMatrix33::operator*(const double scalar) const
-{
-  return FGMatrix33( scalar * Entry(1,1),
-                     scalar * Entry(1,2),
-                     scalar * Entry(1,3),
-                     scalar * Entry(2,1),
-                     scalar * Entry(2,2),
-                     scalar * Entry(2,3),
-                     scalar * Entry(3,1),
-                     scalar * Entry(3,2),
-                     scalar * Entry(3,3) );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33 operator*(double scalar, FGMatrix33 &M)
-{
-  return FGMatrix33( scalar * M(1,1),
-                     scalar * M(1,2),
-                     scalar * M(1,3),
-                     scalar * M(2,1),
-                     scalar * M(2,2),
-                     scalar * M(2,3),
-                     scalar * M(3,1),
-                     scalar * M(3,2),
-                     scalar * M(3,3) );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33& FGMatrix33::operator*=(const double scalar)
-{
-  Entry(1,1) *= scalar;
-  Entry(1,2) *= scalar;
-  Entry(1,3) *= scalar;
-  Entry(2,1) *= scalar;
-  Entry(2,2) *= scalar;
-  Entry(2,3) *= scalar;
-  Entry(3,1) *= scalar;
-  Entry(3,2) *= scalar;
-  Entry(3,3) *= scalar;
-
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const
-{
-  // FIXME: Make compiler friendlier
-  FGMatrix33 Product;
-
-  Product(1,1) = Entry(1,1)*M(1,1) + Entry(1,2)*M(2,1) + Entry(1,3)*M(3,1);
-  Product(1,2) = Entry(1,1)*M(1,2) + Entry(1,2)*M(2,2) + Entry(1,3)*M(3,2);
-  Product(1,3) = Entry(1,1)*M(1,3) + Entry(1,2)*M(2,3) + Entry(1,3)*M(3,3);
-  Product(2,1) = Entry(2,1)*M(1,1) + Entry(2,2)*M(2,1) + Entry(2,3)*M(3,1);
-  Product(2,2) = Entry(2,1)*M(1,2) + Entry(2,2)*M(2,2) + Entry(2,3)*M(3,2);
-  Product(2,3) = Entry(2,1)*M(1,3) + Entry(2,2)*M(2,3) + Entry(2,3)*M(3,3);
-  Product(3,1) = Entry(3,1)*M(1,1) + Entry(3,2)*M(2,1) + Entry(3,3)*M(3,1);
-  Product(3,2) = Entry(3,1)*M(1,2) + Entry(3,2)*M(2,2) + Entry(3,3)*M(3,2);
-  Product(3,3) = Entry(3,1)*M(1,3) + Entry(3,2)*M(2,3) + Entry(3,3)*M(3,3);
-
-  return Product;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M)
-{
-  // FIXME: Make compiler friendlier
-  double a,b,c;
-
-  a = Entry(1,1); b=Entry(1,2); c=Entry(1,3);
-  Entry(1,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
-  Entry(1,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
-  Entry(1,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
-
-  a = Entry(2,1); b=Entry(2,2); c=Entry(2,3);
-  Entry(2,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
-  Entry(2,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
-  Entry(2,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
-
-  a = Entry(3,1); b=Entry(3,2); c=Entry(3,3);
-  Entry(3,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
-  Entry(3,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
-  Entry(3,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
-
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33 FGMatrix33::operator/(const double scalar) const
-{
-  FGMatrix33 Quot;
-
-  if ( scalar != 0 ) {
-    double tmp = 1.0/scalar;
-    Quot(1,1) = Entry(1,1) * tmp;
-    Quot(1,2) = Entry(1,2) * tmp;
-    Quot(1,3) = Entry(1,3) * tmp;
-    Quot(2,1) = Entry(2,1) * tmp;
-    Quot(2,2) = Entry(2,2) * tmp;
-    Quot(2,3) = Entry(2,3) * tmp;
-    Quot(3,1) = Entry(3,1) * tmp;
-    Quot(3,2) = Entry(3,2) * tmp;
-    Quot(3,3) = Entry(3,3) * tmp;
-  } else {
-    MatrixException mE;
-    mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)";
-    throw mE;
-  }
-  return Quot;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33& FGMatrix33::operator/=(const double scalar)
-{
-  if ( scalar != 0 ) {
-    double tmp = 1.0/scalar;
-    Entry(1,1) *= tmp;
-    Entry(1,2) *= tmp;
-    Entry(1,3) *= tmp;
-    Entry(2,1) *= tmp;
-    Entry(2,2) *= tmp;
-    Entry(2,3) *= tmp;
-    Entry(3,1) *= tmp;
-    Entry(3,2) *= tmp;
-    Entry(3,3) *= tmp;
-  } else {
-    MatrixException mE;
-    mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)";
-    throw mE;
-  }
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGMatrix33::T(void)
-{
-  for (unsigned int i=1; i<=3; i++) {
-    for (unsigned int j=i+1; j<=3; j++) {
-      double tmp = Entry(i,j);
-      Entry(i,j) = Entry(j,i);
-      Entry(j,i) = tmp;
-    }
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const {
-  double tmp1 = v(1)*Entry(1,1);
-  double tmp2 = v(1)*Entry(2,1);
-  double tmp3 = v(1)*Entry(3,1);
-
-  tmp1 += v(2)*Entry(1,2);
-  tmp2 += v(2)*Entry(2,2);
-  tmp3 += v(2)*Entry(3,2);
-
-  tmp1 += v(3)*Entry(1,3);
-  tmp2 += v(3)*Entry(2,3);
-  tmp3 += v(3)*Entry(3,3);
-
-  return FGColumnVector3( tmp1, tmp2, tmp3 );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGMatrix33::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: FGMatrix33" << endl;
-    if (from == 1) cout << "Destroyed:    FGMatrix33" << 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/FGMatrix33.h b/src/FDM/JSBSim/FGMatrix33.h
deleted file mode 100644 (file)
index 9bc78ee..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Header: FGMatrix33.h
-Author: Tony Peden, Jon Berndt, Mathias Frolich
-Date started: Unknown
-
-HISTORY
---------------------------------------------------------------------------------
-??/??/??   TP   Created
-03/16/2000 JSB  Added exception throwing
-03/06/2004 MF   Rework of the code to make it a bit compiler friendlier
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGMATRIX33_H
-#define FGMATRIX33_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);
-#else
-#  include <string>
-#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
-     include <fstream.h>
-     include <iostream.h>
-#    include <math.h>
-#  else
-#    include <fstream>
-#    include <iostream>
-#    if defined(sgi) && !defined(__GNUC__)
-#      include <math.h>
-#    else
-#      include <cmath>
-#    endif
-     using std::ostream;
-     using std::istream;
-     using std::cerr;
-     using std::cout;
-     using std::endl;
-#  endif
-   using std::string;
-#endif
-
-#include "FGColumnVector3.h"
-#include "FGJSBBase.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_MATRIX33 "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-class FGColumnVector3;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Exception convenience class.
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DECLARATION: MatrixException
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class MatrixException : public FGJSBBase
-{
-public:
-  string Message;
-};
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-  /** Handles matrix math operations.
-      @author Tony Peden, Jon Berndt, Mathias Froelich
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DECLARATION: FGMatrix33
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGMatrix33 : public FGJSBBase
-{
-public:
-
-  enum {
-    eRows = 3,
-    eColumns = 3
-  };
-
-  /** Default initializer.
-      Create a zero matrix.  */
-  FGMatrix33(void);
-
-  /** Copy constructor.
-      @param M Matrix which is used for initialization.
-      Create copy of the matrix given in the argument.  */
-  FGMatrix33(const FGMatrix33& M) {
-    Entry(1,1) = M.Entry(1,1);
-    Entry(2,1) = M.Entry(2,1);
-    Entry(3,1) = M.Entry(3,1);
-    Entry(1,2) = M.Entry(1,2);
-    Entry(2,2) = M.Entry(2,2);
-    Entry(3,2) = M.Entry(3,2);
-    Entry(1,3) = M.Entry(1,3);
-    Entry(2,3) = M.Entry(2,3);
-    Entry(3,3) = M.Entry(3,3);
-
-    Debug(0);
-  }
-
-  /** Initialization by given values.
-      @param m11 value of the 1,1 Matrix element.
-      @param m12 value of the 1,2 Matrix element.
-      @param m13 value of the 1,3 Matrix element.
-      @param m21 value of the 2,1 Matrix element.
-      @param m22 value of the 2,2 Matrix element.
-      @param m23 value of the 2,3 Matrix element.
-      @param m31 value of the 3,1 Matrix element.
-      @param m32 value of the 3,2 Matrix element.
-      @param m33 value of the 3,3 Matrix element.
-      Create a matrix from the doubles given in the arguments.   */
-  FGMatrix33(double m11, double m12, double m13,
-             double m21, double m22, double m23,
-             double m31, double m32, double m33) {
-    Entry(1,1) = m11;
-    Entry(2,1) = m21;
-    Entry(3,1) = m31;
-    Entry(1,2) = m12;
-    Entry(2,2) = m22;
-    Entry(3,2) = m32;
-    Entry(1,3) = m13;
-    Entry(2,3) = m23;
-    Entry(3,3) = m33;
-
-    Debug(0);
-  }
-
-  /// Destructor.
-  ~FGMatrix33(void) { Debug(1); }
-
-  /** Read access the entries of the matrix.
-      @param row Row index.
-      @param col Column index.
-      @return the value of the matrix entry at the given row and
-      column indices. Indices are counted starting with 1.   */
-  double operator()(unsigned int row, unsigned int col) const {
-    return Entry(row, col);
-  }
-
-  /** Write access the entries of the matrix.
-      Note that the indices given in the arguments are unchecked.
-      @param row Row index.
-      @param col Column index.
-      @return a reference to the matrix entry at the given row and
-      column indices. Indices are counted starting with 1.   */
-  double& operator()(unsigned int row, unsigned int col) {
-    return Entry(row, col);
-  }
-
-  /** Read access the entries of the matrix.
-      This function is just a shortcut for the @ref double&
-      operator()(unsigned int row, unsigned int col) function. It is
-      used internally to access the elements in a more convenient way.
-      Note that the indices given in the arguments are unchecked.
-      @param row Row index.
-      @param col Column index.
-      @return the value of the matrix entry at the given row and
-      column indices. Indices are counted starting with 1.   */
-  double Entry(unsigned int row, unsigned int col) const {
-    return data[(col-1)*eRows+row-1];
-  }
-
-  /** Write access the entries of the matrix.
-      This function is just a shortcut for the @ref double&
-      operator()(unsigned int row, unsigned int col) function. It is
-      used internally to access the elements in a more convenient way.
-      Note that the indices given in the arguments are unchecked.
-      @param row Row index.
-      @param col Column index.
-      @return a reference to the matrix entry at the given row and
-      column indices. Indices are counted starting with 1.   */
-   double& Entry(unsigned int row, unsigned int col) {
-     return data[(col-1)*eRows+row-1];
-   }
-
-  /** Number of rows in the matrix.
-      @return the number of rows in the matrix.   */
-   unsigned int Rows(void) const { return eRows; }
-
-  /** Number of cloumns in the matrix.
-      @return the number of columns in the matrix.   */
-   unsigned int Cols(void) const { return eColumns; }
-
-  /** Transposed matrix.
-      This function only returns the transpose of this matrix. This matrix itself
-      remains unchanged.
-      @return the transposed matrix.   */
-  FGMatrix33 Transposed(void) const {
-    return FGMatrix33( Entry(1,1), Entry(2,1), Entry(3,1),
-                       Entry(1,2), Entry(2,2), Entry(3,2),
-                       Entry(1,3), Entry(2,3), Entry(3,3) );
-  }
-
-  /** Transposes this matrix.
-      This function only transposes this matrix. Nothing is returned.   */
-  void T(void);
-
-/** Initialize the matrix.
-    This function initializes a matrix to all 0.0. */
-  void InitMatrix(void);
-
-/** Initialize the matrix.
-    This function initializes a matrix to user specified values. */
-  void InitMatrix(double m11, double m12, double m13,
-                  double m21, double m22, double m23,
-                  double m31, double m32, double m33) {
-    Entry(1,1) = m11;
-    Entry(2,1) = m21;
-    Entry(3,1) = m31;
-    Entry(1,2) = m12;
-    Entry(2,2) = m22;
-    Entry(3,2) = m32;
-    Entry(1,3) = m13;
-    Entry(2,3) = m23;
-    Entry(3,3) = m33;
-  }
-
-  /** Determinant of the matrix.
-      @return the determinant of the matrix.   */
-  double Determinant(void) const;
-
-  /** Return if the matrix is invertible.
-      Checks and returns if the matrix is nonsingular and thus
-      invertible. This is done by simply computing the determinant and
-      check if it is zero. Note that this test does not cover any
-      instabilities caused by nearly singular matirces using finite
-      arithmetics. It only checks exact singularity.   */
-  bool Invertible(void) const { return 0.0 != Determinant(); }
-
-  /** Return the inverse of the matrix.
-      Computes and returns if the inverse of the matrix. It is computed
-      by Cramers Rule. Also there are no checks performed if the matrix
-      is invertible. If you are not sure that it really is check this
-      with the @ref Invertible() call before.   */
-  FGMatrix33 Inverse(void) const;
-
-  /** Assignment operator.
-      @param A source matrix.
-      Copy the content of the matrix given in the argument into *this.   */
-  FGMatrix33& operator=(const FGMatrix33& A) {
-    data[0] = A.data[0];
-    data[1] = A.data[1];
-    data[2] = A.data[2];
-    data[3] = A.data[3];
-    data[4] = A.data[4];
-    data[5] = A.data[5];
-    data[6] = A.data[6];
-    data[7] = A.data[7];
-    data[8] = A.data[8];
-    return *this;
-  }
-
-  /** Matrix vector multiplication.
-      @param v vector to multiply with.
-      @return matric vector product.
-      Compute and return the product of the current matrix with the
-      vector given in the argument.   */
-  FGColumnVector3 operator*(const FGColumnVector3& v) const;
-
-  /** Matrix subtraction.
-      @param B matrix to add to.
-      @return difference of the matrices.
-      Compute and return the sum of the current matrix and the matrix
-      B given in the argument.  */
-  FGMatrix33 operator-(const FGMatrix33& B) const;
-
-  /** Matrix addition.
-      @param B matrix to add to.
-      @return sum of the matrices.
-      Compute and return the sum of the current matrix and the matrix
-      B given in the argument.  */
-  FGMatrix33 operator+(const FGMatrix33& B) const;
-
-  /** Matrix product.
-      @param B matrix to add to.
-      @return product of the matrices.
-      Compute and return the product of the current matrix and the matrix
-      B given in the argument.  */
-  FGMatrix33 operator*(const FGMatrix33& B) const;
-
-  /** Multiply the matrix with a scalar.
-      @param scalar scalar factor to multiply with.
-      @return scaled matrix.
-      Compute and return the product of the current matrix with the
-      scalar value scalar given in the argument.  */
-  FGMatrix33 operator*(const double scalar) const;
-
-  /** Multiply the matrix with 1.0/scalar.
-      @param scalar scalar factor to divide through.
-      @return scaled matrix.
-      Compute and return the product of the current matrix with the
-      scalar value 1.0/scalar, where scalar is given in the argument.  */
-  FGMatrix33 operator/(const double scalar) const;
-
-  /** In place matrix subtraction.
-      @param B matrix to subtract.
-      @return reference to the current matrix.
-      Compute the diffence from the current matrix and the matrix B
-      given in the argument.  */
-  FGMatrix33& operator-=(const FGMatrix33 &B);
-
-  /** In place matrix addition.
-      @param B matrix to add.
-      @return reference to the current matrix.
-      Compute the sum of the current matrix and the matrix B
-      given in the argument.  */
-  FGMatrix33& operator+=(const FGMatrix33 &B);
-
-  /** In place matrix multiplication.
-      @param B matrix to multiply with.
-      @return reference to the current matrix.
-      Compute the product of the current matrix and the matrix B
-      given in the argument.  */
-  FGMatrix33& operator*=(const FGMatrix33 &B);
-
-  /** In place matrix scale.
-      @param scalar scalar value to multiply with.
-      @return reference to the current matrix.
-      Compute the product of the current matrix and the scalar value scalar
-      given in the argument.  */
-  FGMatrix33& operator*=(const double scalar);
-
-  /** In place matrix scale.
-      @param scalar scalar value to divide through.
-      @return reference to the current matrix.
-      Compute the product of the current matrix and the scalar value
-      1.0/scalar, where scalar is given in the argument.  */
-  FGMatrix33& operator/=(const double scalar);
-
-private:
-  double data[eRows*eColumns];
-
-  void Debug(int from);
-};
-
-/** Scalar multiplication.
-    @param scalar scalar value to multiply with.
-    @param A Matrix to multiply.
-    Multiply the Matrix with a scalar value.*/
-inline FGMatrix33 operator*(double scalar, const FGMatrix33& A) {
-  // use already defined operation.
-  return A*scalar;
-}
-
-/** Write matrix to a stream.
-    @param os Stream to write to.
-    @param M Matrix to write.
-    Write the matrix to a stream.*/
-ostream& operator<<(ostream& os, const FGMatrix33& M);
-
-/** Read matrix from a stream.
-    @param os Stream to read from.
-    @param M Matrix to initialize with the values from the stream.
-    Read matrix from a stream.*/
-istream& operator>>(istream& is, FGMatrix33& M);
-
-} // namespace JSBSim
-
-#endif
diff --git a/src/FDM/JSBSim/FGModel.cpp b/src/FDM/JSBSim/FGModel.cpp
deleted file mode 100644 (file)
index 3482baf..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGModel.cpp
- Author:       Jon Berndt
- Date started: 11/11/98
- Purpose:      Base class for all models
- Called by:    FGSimExec, 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 base class for the FGAerodynamics, FGPropagate, etc. classes defines methods
-common to all models.
-
-HISTORY
---------------------------------------------------------------------------------
-11/11/98   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGModel.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-#include "FGAtmosphere.h"
-#include "FGFCS.h"
-#include "FGPropulsion.h"
-#include "FGMassBalance.h"
-#include "FGAerodynamics.h"
-#include "FGInertial.h"
-#include "FGGroundReactions.h"
-#include "FGAircraft.h"
-#include "FGPropagate.h"
-#include "FGAuxiliary.h"
-#include "FGOutput.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_MODEL;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-GLOBAL DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGModel::FGModel(FGFDMExec* fdmex)
-{
-  FDMExec     = fdmex;
-  NextModel   = 0L;
-
-  State           = 0;
-  Atmosphere      = 0;
-  FCS             = 0;
-  Propulsion      = 0;
-  MassBalance     = 0;
-  Aerodynamics    = 0;
-  Inertial        = 0;
-  GroundReactions = 0;
-  Aircraft        = 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;
-
-  if (debug_lvl & 2) cout << "              FGModel Base Class" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGModel::~FGModel()
-{
-  if (debug_lvl & 2) cout << "Destroyed:    FGModel" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGModel::InitModel(void)
-{
-  State           = FDMExec->GetState();
-  Atmosphere      = FDMExec->GetAtmosphere();
-  FCS             = FDMExec->GetFCS();
-  Propulsion      = FDMExec->GetPropulsion();
-  MassBalance     = FDMExec->GetMassBalance();
-  Aerodynamics    = FDMExec->GetAerodynamics();
-  Inertial        = FDMExec->GetInertial();
-  GroundReactions = FDMExec->GetGroundReactions();
-  Aircraft        = FDMExec->GetAircraft();
-  Propagate       = FDMExec->GetPropagate();
-  Auxiliary       = FDMExec->GetAuxiliary();
-  Output          = FDMExec->GetOutput();
-
-  if (!State ||
-      !Atmosphere ||
-      !FCS ||
-      !Propulsion ||
-      !MassBalance ||
-      !Aerodynamics ||
-      !Inertial ||
-      !GroundReactions ||
-      !Aircraft ||
-      !Propagate ||
-      !Auxiliary ||
-      !Output) return(false);
-  else return(true);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGModel::Run()
-{
-  if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;
-
-  if (exe_ctr == 1) {
-    if (exe_ctr++ >= rate) exe_ctr = 1;
-    return false;
-  } else {
-    if (exe_ctr++ >= rate) exe_ctr = 1;
-    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 FGModel::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: FGModel" << endl;
-    if (from == 1) cout << "Destroyed:    FGModel" << 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/FGModel.h b/src/FDM/JSBSim/FGModel.h
deleted file mode 100644 (file)
index 6ae3707..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGModel.h
- Author:       Jon Berndt
- Date started: 11/21/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
---------------------------------------------------------------------------------
-11/22/98   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGMODEL_H
-#define FGMODEL_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGJSBBase.h"
-#include "FGPropertyManager.h"
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <iostream>
-#  else
-#    include <iostream.h>
-#  endif
-#else
-#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
-#    include <iostream.h>
-#  else
-#    include <iostream>
-#  endif
-#endif
-
-#include <string>
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_MODEL "$Id$"
-
-using namespace std;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-class FGFDMExec;
-class FGState;
-class FGAtmosphere;
-class FGFCS;
-class FGPropulsion;
-class FGMassBalance;
-class FGAerodynamics;
-class FGInertial;
-class FGGroundReactions;
-class FGAircraft;
-class FGPropagate;
-class FGAuxiliary;
-class FGOutput;
-class FGConfigFile;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Base class for all scheduled JSBSim models
-    @author Jon S. Berndt
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGModel : public FGJSBBase
-{
-public:
-
-  /// Constructor
-  FGModel(FGFDMExec*);
-  /// Destructor
-  virtual ~FGModel();
-
-  /** Loads this model.
-      @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;
-
-  /** Runs the model; called by the Executive
-      @see JSBSim.cpp documentation
-      @return false if no error */
-  virtual bool Run(void);
-  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;
-  FGState*           State;
-  FGAtmosphere*      Atmosphere;
-  FGFCS*             FCS;
-  FGPropulsion*      Propulsion;
-  FGMassBalance*     MassBalance;
-  FGAerodynamics*    Aerodynamics;
-  FGInertial*        Inertial;
-  FGGroundReactions* GroundReactions;
-  FGAircraft*        Aircraft;
-  FGPropagate*       Propagate;
-  FGAuxiliary*       Auxiliary;
-  FGOutput*          Output;
-  FGPropertyManager* PropertyManager;
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGNozzle.cpp b/src/FDM/JSBSim/FGNozzle.cpp
deleted file mode 100644 (file)
index fa04703..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGNozzle.cpp
- Author:       Jon S. Berndt
- Date started: 08/24/00
- Purpose:      Encapsulates the nozzle object
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/24/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <sstream>
-
-#include "FGNozzle.h"
-#include "FGAtmosphere.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_NOZZLE;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGNozzle::FGNozzle(FGFDMExec* FDMExec, FGConfigFile* Nzl_cfg, int num) : FGThruster(FDMExec)
-{
-  string token;
-
-  Name = Nzl_cfg->GetValue("NAME");
-  Nzl_cfg->GetNextConfigLine();
-  while (Nzl_cfg->GetValue() != string("/FG_NOZZLE")) {
-    *Nzl_cfg >> token;
-    if      (token == "PE")      *Nzl_cfg >> PE;
-    else if (token == "EXPR")    *Nzl_cfg >> ExpR;
-    else if (token == "NZL_EFF") *Nzl_cfg >> nzlEff;
-    else if (token == "DIAM")    *Nzl_cfg >> Diameter;
-    else cerr << "Unhandled token in Nozzle config file: " << token << endl;
-  }
-
-  Thrust = 0;
-  Type = ttNozzle;
-  Area2 = (Diameter*Diameter/4.0)*M_PI;
-  AreaT = Area2/ExpR;
-
-  char property_name[80];
-  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
-  PropertyManager->Tie( property_name, &ThrustCoeff );
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGNozzle::~FGNozzle()
-{
-  char property_name[80];
-  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
-  PropertyManager->Untie( property_name );
-
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGNozzle::Calculate(double CfPc)
-{
-  double pAtm = fdmex->GetAtmosphere()->GetPressure();
-  Thrust = max((double)0.0, (CfPc * AreaT + (PE - pAtm)*Area2) * nzlEff);
-  vFn(1) = Thrust;
-
-  ThrustCoeff = max((double)0.0, CfPc / ((pAtm - PE) * Area2));
-
-  return Thrust;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGNozzle::GetPowerRequired(void)
-{
-  return PE;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGNozzle::GetThrusterLabels(int id, string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << Name << "_Thrust[" << id << ']';
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGNozzle::GetThrusterValues(int id, string delimeter)
-{
-  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
-//       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 FGNozzle::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "      Nozzle Name: " << Name << endl;
-      cout << "      Nozzle Exit Pressure = " << PE << endl;
-      cout << "      Nozzle Expansion Ratio = " << ExpR << endl;
-      cout << "      Nozzle Efficiency = " << nzlEff << endl;
-      cout << "      Nozzle Diameter = " << Diameter << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGNozzle" << endl;
-    if (from == 1) cout << "Destroyed:    FGNozzle" << 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/FGNozzle.h b/src/FDM/JSBSim/FGNozzle.h
deleted file mode 100644 (file)
index d329fa1..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGNozzle.h
- Author:       Jon S. Berndt
- Date started: 08/24/00
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/24/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGNOZZLE_H
-#define FGNOZZLE_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGThruster.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_NOZZLE "$Id$";
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models a rocket nozzle.
-    @author Jon S. Berndt
-    @version $Id$
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGNozzle : public FGThruster {
-
-public:
-  /// Constructor
-  FGNozzle(FGFDMExec* exec, FGConfigFile* AC_cfg, int num = 0);
-  /// Destructor
-  ~FGNozzle();
-
-  double Calculate(double CfPc);
-  double GetPowerRequired(void);
-  string GetThrusterLabels(int id, string delimeter);
-  string GetThrusterValues(int id, string delimeter);
-
-private:
-
-  double PE;
-  double ExpR;
-  double nzlEff;
-  double Diameter;
-  double AreaT;
-  double Area2;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGOutput.cpp b/src/FDM/JSBSim/FGOutput.cpp
deleted file mode 100644 (file)
index dc3e43f..0000000
+++ /dev/null
@@ -1,641 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGOutput.cpp
- Author:       Jon Berndt
- Date started: 12/02/98
- Purpose:      Manage output of sim parameters to file or stdout
- 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
- 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 is the place where you create output routines to dump data for perusal
-later.
-
-HISTORY
---------------------------------------------------------------------------------
-12/02/98   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGOutput.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-#include "FGAtmosphere.h"
-#include "FGFCS.h"
-#include "FGAerodynamics.h"
-#include "FGGroundReactions.h"
-#include "FGAircraft.h"
-#include "FGMassBalance.h"
-#include "FGPropagate.h"
-#include "FGAuxiliary.h"
-#include "FGInertial.h"
-
-#include <iomanip>
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_OUTPUT;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
-{
-  Name = "FGOutput";
-  sFirstPass = dFirstPass = true;
-  socket = 0;
-  Type = otNone;
-  Filename = "";
-  SubSystems = 0;
-  enabled = true;
-  outputInFileName = "";
-  delimeter = ", ";
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGOutput::~FGOutput()
-{
-  if (socket) delete socket;
-  for (unsigned int i=0; i<OutputProperties.size(); i++) delete OutputProperties[i];
-
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGOutput::Run(void)
-{
-  if (enabled) {
-    if (FGModel::Run()) return true;
-    if (Type == otSocket) {
-      SocketOutput();
-    } else if (Type == otCSV || Type == otTab) {
-      DelimitedOutput(Filename);
-    } else if (Type == otTerminal) {
-      // Not done yet
-    } else if (Type == otNone) {
-      // Do nothing
-    } else {
-      // Not a valid type of output
-    }
-  }
-  return false;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGOutput::SetType(string type)
-{
-  if (type == "CSV") {
-    Type = otCSV;
-    delimeter = ", ";
-  } else if (type == "TABULAR") {
-    Type = otTab;
-    delimeter = "\t";
-  } else if (type == "SOCKET") {
-    Type = otSocket;
-  } else if (type == "TERMINAL") {
-    Type = otTerminal;
-  } else if (type != string("NONE")) {
-    Type = otUnknown;
-    cerr << "Unknown type of output specified in config file" << endl;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGOutput::DelimitedOutput(string fname)
-{
-  streambuf* buffer;
-  string scratch = "";
-
-  if (fname == "COUT" || fname == "cout") {
-    buffer = cout.rdbuf();
-  } else {
-    datafile.open(fname.c_str());
-    buffer = datafile.rdbuf();
-  }
-
-  ostream outstream(buffer);
-
-  if (dFirstPass) {
-    outstream << "Time";
-    if (SubSystems & ssSimulation) {
-      // Nothing here, yet
-    }
-    if (SubSystems & ssAerosurfaces) {
-      outstream << delimeter;
-      outstream << "Aileron Cmd" + delimeter;
-      outstream << "Elevator Cmd" + delimeter;
-      outstream << "Rudder Cmd" + delimeter;
-      outstream << "Flap Cmd" + delimeter;
-      outstream << "Left Aileron Pos" + delimeter;
-      outstream << "Right Aileron Pos" + delimeter;
-      outstream << "Elevator Pos" + delimeter;
-      outstream << "Rudder Pos" + delimeter;
-      outstream << "Flap Pos";
-    }
-    if (SubSystems & ssRates) {
-      outstream << delimeter;
-      outstream << "P" + delimeter + "Q" + delimeter + "R" + delimeter;
-      outstream << "Pdot" + delimeter + "Qdot" + delimeter + "Rdot";
-    }
-    if (SubSystems & ssVelocities) {
-      outstream << delimeter;
-      outstream << "QBar" + delimeter;
-      outstream << "Vtotal" + delimeter;
-      outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
-      outstream << "UAero" + delimeter + "VAero" + delimeter + "WAero" + delimeter;
-      outstream << "Vn" + delimeter + "Ve" + delimeter + "Vd";
-    }
-    if (SubSystems & ssForces) {
-      outstream << delimeter;
-      outstream << "Drag" + delimeter + "Side" + delimeter + "Lift" + delimeter;
-      outstream << "L/D" + delimeter;
-      outstream << "Xforce" + delimeter + "Yforce" + delimeter + "Zforce";
-    }
-    if (SubSystems & ssMoments) {
-      outstream << delimeter;
-      outstream << "L" + delimeter + "M" + delimeter + "N";
-    }
-    if (SubSystems & ssAtmosphere) {
-      outstream << delimeter;
-      outstream << "Rho" + delimeter;
-      outstream << "NWind" + delimeter + "EWind" + delimeter + "DWind";
-    }
-    if (SubSystems & ssMassProps) {
-      outstream << delimeter;
-      outstream << "Ixx" + delimeter;
-      outstream << "Ixy" + delimeter;
-      outstream << "Ixz" + delimeter;
-      outstream << "Iyx" + delimeter;
-      outstream << "Iyy" + delimeter;
-      outstream << "Iyz" + delimeter;
-      outstream << "Izx" + delimeter;
-      outstream << "Izy" + delimeter;
-      outstream << "Izz" + delimeter;
-      outstream << "Mass" + delimeter;
-      outstream << "Xcg" + delimeter + "Ycg" + delimeter + "Zcg";
-    }
-    if (SubSystems & ssPropagate) {
-      outstream << delimeter;
-      outstream << "Altitude" + delimeter;
-      outstream << "Phi" + delimeter + "Tht" + delimeter + "Psi" + delimeter;
-      outstream << "Alpha" + delimeter;
-      outstream << "Beta" + delimeter;
-      outstream << "Latitude (Deg)" + delimeter;
-      outstream << "Longitude (Deg)" + delimeter;
-      outstream << "Distance AGL" + delimeter;
-      outstream << "Runway Radius";
-    }
-    if (SubSystems & ssCoefficients) {
-      scratch = Aerodynamics->GetCoefficientStrings(delimeter);
-      if (scratch.length() != 0) outstream << delimeter << scratch;
-    }
-    if (SubSystems & ssFCS) {
-      scratch = FCS->GetComponentStrings(delimeter);
-      if (scratch.length() != 0) outstream << delimeter << scratch;
-    }
-    if (SubSystems & ssGroundReactions) {
-      outstream << delimeter;
-      outstream << GroundReactions->GetGroundReactionStrings(delimeter);
-    }
-    if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
-      outstream << delimeter;
-      outstream << Propulsion->GetPropulsionStrings(delimeter);
-    }
-    if (OutputProperties.size() > 0) {
-      for (unsigned int i=0;i<OutputProperties.size();i++) {
-        outstream << delimeter << OutputProperties[i]->GetName();
-      }
-    }
-
-    outstream << endl;
-    dFirstPass = false;
-  }
-
-  outstream << State->Getsim_time();
-  if (SubSystems & ssSimulation) {
-  }
-  if (SubSystems & ssAerosurfaces) {
-    outstream << delimeter;
-    outstream << FCS->GetDaCmd() << delimeter;
-    outstream << FCS->GetDeCmd() << delimeter;
-    outstream << FCS->GetDrCmd() << delimeter;
-    outstream << FCS->GetDfCmd() << delimeter;
-    outstream << FCS->GetDaLPos() << delimeter;
-    outstream << FCS->GetDaRPos() << delimeter;
-    outstream << FCS->GetDePos() << delimeter;
-    outstream << FCS->GetDrPos() << delimeter;
-    outstream << FCS->GetDfPos();
-  }
-  if (SubSystems & ssRates) {
-    outstream << delimeter;
-    outstream << Propagate->GetPQR().Dump(delimeter) << delimeter;
-    outstream << Propagate->GetPQRdot().Dump(delimeter);
-  }
-  if (SubSystems & ssVelocities) {
-    outstream << delimeter;
-    outstream << Auxiliary->Getqbar() << delimeter;
-    outstream << setprecision(12) << Auxiliary->GetVt() << delimeter;
-    outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
-    outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
-    outstream << Propagate->GetVel().Dump(delimeter);
-  }
-  if (SubSystems & ssForces) {
-    outstream << delimeter;
-    outstream << Aerodynamics->GetvFs() << delimeter;
-    outstream << Aerodynamics->GetLoD() << delimeter;
-    outstream << Aircraft->GetForces().Dump(delimeter);
-  }
-  if (SubSystems & ssMoments) {
-    outstream << delimeter;
-    outstream << Aircraft->GetMoments().Dump(delimeter);
-  }
-  if (SubSystems & ssAtmosphere) {
-    outstream << delimeter;
-    outstream << Atmosphere->GetDensity() << delimeter;
-    outstream << Atmosphere->GetWindNED().Dump(delimeter);
-  }
-  if (SubSystems & ssMassProps) {
-    outstream << delimeter;
-    outstream << MassBalance->GetJ() << delimeter;
-    outstream << MassBalance->GetMass() << delimeter;
-    outstream << MassBalance->GetXYZcg();
-  }
-  if (SubSystems & ssPropagate) {
-    outstream << delimeter;
-    outstream << Propagate->Geth() << delimeter;
-    outstream << Propagate->GetEuler().Dump(delimeter) << delimeter;
-    outstream << Auxiliary->Getalpha(inDegrees) << delimeter;
-    outstream << Auxiliary->Getbeta(inDegrees) << delimeter;
-    outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter;
-    outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter;
-    outstream << Propagate->GetDistanceAGL() << delimeter;
-    outstream << Propagate->GetRunwayRadius();
-  }
-  if (SubSystems & ssCoefficients) {
-    scratch = Aerodynamics->GetCoefficientValues(delimeter);
-    if (scratch.length() != 0) outstream << delimeter << scratch;
-  }
-  if (SubSystems & ssFCS) {
-    scratch = FCS->GetComponentValues(delimeter);
-    if (scratch.length() != 0) outstream << delimeter << scratch;
-  }
-  if (SubSystems & ssGroundReactions) {
-    outstream << delimeter;
-    outstream << GroundReactions->GetGroundReactionValues(delimeter);
-  }
-  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
-    outstream << delimeter;
-    outstream << Propulsion->GetPropulsionValues(delimeter);
-  }
-
-  for (unsigned int i=0;i<OutputProperties.size();i++) {
-    outstream << delimeter << OutputProperties[i]->getDoubleValue();
-  }
-
-  outstream << endl;
-  outstream.flush();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGOutput::SocketOutput(void)
-{
-  string asciiData;
-
-  if (socket == NULL) return;
-  if (!socket->GetConnectStatus()) return;
-
-  socket->Clear();
-  if (sFirstPass) {
-    socket->Append("<LABELS>");
-    socket->Append("Time");
-    socket->Append("Altitude");
-    socket->Append("Phi");
-    socket->Append("Tht");
-    socket->Append("Psi");
-    socket->Append("Rho");
-    socket->Append("Vtotal");
-    socket->Append("UBody");
-    socket->Append("VBody");
-    socket->Append("WBody");
-    socket->Append("UAero");
-    socket->Append("VAero");
-    socket->Append("WAero");
-    socket->Append("Vn");
-    socket->Append("Ve");
-    socket->Append("Vd");
-    socket->Append("Udot");
-    socket->Append("Vdot");
-    socket->Append("Wdot");
-    socket->Append("P");
-    socket->Append("Q");
-    socket->Append("R");
-    socket->Append("PDot");
-    socket->Append("QDot");
-    socket->Append("RDot");
-    socket->Append("Fx");
-    socket->Append("Fy");
-    socket->Append("Fz");
-    socket->Append("Latitude (Deg)");
-    socket->Append("Longitude (Deg)");
-    socket->Append("QBar");
-    socket->Append("Alpha");
-    socket->Append("L");
-    socket->Append("M");
-    socket->Append("N");
-    socket->Append("Throttle Position");
-    socket->Append("Left Aileron Position");
-    socket->Append("Right Aileron Position");
-    socket->Append("Elevator Position");
-    socket->Append("Rudder Position");
-    sFirstPass = false;
-    socket->Send();
-  }
-
-  socket->Clear();
-  socket->Append(State->Getsim_time());
-  socket->Append(Propagate->Geth());
-  socket->Append(Propagate->GetEuler(ePhi));
-  socket->Append(Propagate->GetEuler(eTht));
-  socket->Append(Propagate->GetEuler(ePsi));
-  socket->Append(Atmosphere->GetDensity());
-  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(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));
-  socket->Append(FCS->GetThrottlePos(0));
-  socket->Append(FCS->GetDaLPos());
-  socket->Append(FCS->GetDaRPos());
-  socket->Append(FCS->GetDePos());
-  socket->Append(FCS->GetDrPos());
-  socket->Send();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGOutput::SocketStatusOutput(string out_str)
-{
-  string asciiData;
-
-  if (socket == NULL) return;
-
-  socket->Clear();
-  asciiData = string("<STATUS>") + out_str;
-  socket->Append(asciiData.c_str());
-  socket->Send();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGOutput::Load(FGConfigFile* AC_cfg)
-{
-  string token="", parameter="", separator="";
-  string name="", fname="";
-  int OutRate = 0;
-  FGConfigFile* Output_cfg;
-  string property;
-  unsigned int port;
-
-# ifndef macintosh
-    separator = "/";
-# else
-    separator = ";";
-# endif
-
-  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 (token == "SOCKET") {
-    socket = new FGfdmSocket(name,port);
-  }
-
-  if (!fname.empty()) {
-    outputInFileName = FDMExec->GetAircraftPath() + separator
-                        + FDMExec->GetModelName() + separator + fname + ".xml";
-    Output_cfg = new FGConfigFile(outputInFileName);
-    if (!Output_cfg->IsOpen()) {
-      cerr << "Could not open file: " << outputInFileName << endl;
-      return false;
-    }
-  } else {
-    Output_cfg = AC_cfg;
-  }
-  Output->SetFilename(name);
-
-  while ((token = Output_cfg->GetValue()) != string("/OUTPUT")) {
-    *Output_cfg >> parameter;
-    if (parameter == "RATE_IN_HZ") {
-      *Output_cfg >> OutRate;
-    }
-    if (parameter == "SIMULATION") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssSimulation;
-    }
-    if (parameter == "AEROSURFACES") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssAerosurfaces;
-    }
-    if (parameter == "RATES") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssRates;
-    }
-    if (parameter == "VELOCITIES") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssVelocities;
-    }
-    if (parameter == "FORCES") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssForces;
-    }
-    if (parameter == "MOMENTS") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssMoments;
-    }
-    if (parameter == "ATMOSPHERE") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssAtmosphere;
-    }
-    if (parameter == "MASSPROPS") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssMassProps;
-    }
-    if (parameter == "POSITION") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssPropagate;
-    }
-    if (parameter == "COEFFICIENTS") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssCoefficients;
-    }
-    if (parameter == "GROUND_REACTIONS") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssGroundReactions;
-    }
-    if (parameter == "FCS") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssFCS;
-    }
-    if (parameter == "PROPULSION") {
-      *Output_cfg >> parameter;
-      if (parameter == "ON") SubSystems += ssPropulsion;
-    }
-    if (parameter == "PROPERTY") {
-      *Output_cfg >> property;
-      OutputProperties.push_back(PropertyManager->GetNode(property));
-    }
-
-    if (parameter == "EOF") break;
-  }
-
-  OutRate = OutRate>120?120:(OutRate<0?0:OutRate);
-  rate = (int)(0.5 + 1.0/(State->Getdt()*OutRate));
-
-  Debug(2);
-
-  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 FGOutput::Debug(int from)
-{
-  string scratch="";
-
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-
-    }
-    if (from == 2) {
-      if (outputInFileName.empty())
-        cout << "  " << "Output parameters read inline" << endl;
-      else
-        cout << "    Output parameters read from file: " << outputInFileName << endl;
-
-      if (Filename == "cout" || Filename == "COUT") {
-        scratch = "    Log output goes to screen console";
-      } else if (!Filename.empty()) {
-        scratch = "    Log output goes to file: " + Filename;
-      }
-      switch (Type) {
-      case otCSV:
-        cout << scratch << " in CSV format output at rate " << 120/rate << " Hz" << endl;
-        break;
-      case otNone:
-        cout << "  No log output" << endl;
-        break;
-      }
-
-      if (SubSystems & ssSimulation)      cout << "    Simulation parameters logged" << endl;
-      if (SubSystems & ssAerosurfaces)    cout << "    Aerosurface parameters logged" << endl;
-      if (SubSystems & ssRates)           cout << "    Rate parameters logged" << endl;
-      if (SubSystems & ssVelocities)      cout << "    Velocity parameters logged" << endl;
-      if (SubSystems & ssForces)          cout << "    Force parameters logged" << endl;
-      if (SubSystems & ssMoments)         cout << "    Moments parameters logged" << endl;
-      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 & 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
-    if (from == 0) cout << "Instantiated: FGOutput" << endl;
-    if (from == 1) cout << "Destroyed:    FGOutput" << 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/FGOutput.h b/src/FDM/JSBSim/FGOutput.h
deleted file mode 100644 (file)
index 410e62f..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGOutput.h
- Author:       Jon Berndt
- Date started: 12/2/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 FGOUTPUT_H
-#define FGOUTPUT_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGModel.h"
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  include STL_IOSTREAM
-#  include STL_FSTREAM
-#else
-#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
-#    include <iostream.h>
-#    include <fstream.h>
-#  else
-#    include <iostream>
-#    include <fstream>
-#  endif
-#endif
-
-#include "FGfdmSocket.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_OUTPUT "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGOutput : public FGModel
-{
-public:
-  FGOutput(FGFDMExec*);
-  ~FGOutput();
-
-  bool Run(void);
-
-  void DelimitedOutput(string);
-  void SocketOutput(void);
-  void SocketStatusOutput(string);
-  void SetFilename(string fn) {Filename = fn;}
-  void SetType(string);
-  void SetSubsystems(int tt) {SubSystems = tt;}
-  inline void Enable(void) { enabled = true; }
-  inline void Disable(void) { enabled = false; }
-  inline bool Toggle(void) {enabled = !enabled; return enabled;}
-  bool Load(FGConfigFile* AC_cfg);
-
-  /// Subsystem types for specifying which will be output in the FDM data logging
-  enum  eSubSystems {
-    /** Subsystem: Simulation (= 1)          */ ssSimulation      = 1,
-    /** Subsystem: Aerosurfaces (= 2)        */ ssAerosurfaces    = 2,
-    /** Subsystem: Body rates (= 4)          */ ssRates           = 4,
-    /** Subsystem: Velocities (= 8)          */ ssVelocities      = 8,
-    /** Subsystem: Forces (= 16)             */ ssForces          = 16,
-    /** Subsystem: Moments (= 32)            */ ssMoments         = 32,
-    /** Subsystem: Atmosphere (= 64)         */ ssAtmosphere      = 64,
-    /** Subsystem: Mass Properties (= 128)   */ ssMassProps       = 128,
-    /** Subsystem: Coefficients (= 256)      */ ssCoefficients    = 256,
-    /** Subsystem: Propagate (= 512)         */ ssPropagate       = 512,
-    /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024,
-    /** Subsystem: FCS (= 2048)              */ ssFCS             = 2048,
-    /** Subsystem: Propulsion (= 4096)       */ ssPropulsion      = 4096
-  } subsystems;
-
-private:
-  bool sFirstPass, dFirstPass, enabled;
-  int SubSystems;
-  string Filename, outputInFileName, delimeter;
-  enum {otNone, otCSV, otTab, otSocket, otTerminal, otUnknown} Type;
-  ofstream datafile;
-  FGfdmSocket* socket;
-  vector <FGPropertyManager*> OutputProperties;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGPiston.cpp b/src/FDM/JSBSim/FGPiston.cpp
deleted file mode 100644 (file)
index 9c7530e..0000000
+++ /dev/null
@@ -1,808 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGPiston.cpp
- Author:       Jon S. Berndt, JSBSim framework
-               Dave Luff, Piston engine model
- Date started: 09/12/2000
- Purpose:      This module models a Piston engine
-
- ------------- Copyright (C) 2000  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 descends from the FGEngine class and models a Piston engine based on
-parameters given in the engine config file for this class
-
-HISTORY
---------------------------------------------------------------------------------
-09/12/2000  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <sstream>
-
-#include "FGPiston.h"
-#include "FGPropulsion.h"
-#include "FGPropeller.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_PISTON;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number)
-  : FGEngine(exec, engine_number),
-  R_air(287.3),
-  rho_fuel(800),                 // estimate
-  calorific_value_fuel(47.3e6),
-  Cp_air(1005),
-  Cp_fuel(1700)
-{
-  string token;
-
-  Type = etPiston;
-  crank_counter = 0;
-  OilTemp_degK = 298;
-  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 = 0;
-  Cycles = 2;
-  IdleRPM = 600;
-  Magnetos = 0;
-  ExhaustGasTemp_degK = 0.0;
-  EGT_degC = 0.0;
-
-  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;
-  }
-  for (i=0; i<FG_MAX_BOOST_SPEEDS-1; i++) {
-    BoostSwitchAltitude[i] = 0.0;
-    BoostSwitchPressure[i] = 0.0;
-  }
-
-  // Initialisation
-  volumetric_efficiency = 0.8;  // Actually f(speed, load) but this will get us running
-
-  // 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;
-
-  Power_Mixture_Correlation = new FGTable(13);
-  *Power_Mixture_Correlation << (14.7/1.6) << 78.0;
-  *Power_Mixture_Correlation << 10 <<  86.0;
-  *Power_Mixture_Correlation << 11 <<  93.5;
-  *Power_Mixture_Correlation << 12 <<  98.0;
-  *Power_Mixture_Correlation << 13 << 100.0;
-  *Power_Mixture_Correlation << 14 <<  99.0;
-  *Power_Mixture_Correlation << 15 <<  96.4;
-  *Power_Mixture_Correlation << 16 <<  92.5;
-  *Power_Mixture_Correlation << 17 <<  88.0;
-  *Power_Mixture_Correlation << 18 <<  83.0;
-  *Power_Mixture_Correlation << 19 <<  78.5;
-  *Power_Mixture_Correlation << 20 <<  74.0;
-  *Power_Mixture_Correlation << (14.7/0.6) << 58;
-
-  Name = Eng_cfg->GetValue("NAME");
-  Eng_cfg->GetNextConfigLine();
-  while (Eng_cfg->GetValue() != string("/FG_PISTON")) {
-    *Eng_cfg >> token;
-    if      (token == "MINMP") *Eng_cfg >> MinManifoldPressure_inHg;
-    else if (token == "MAXMP") *Eng_cfg >> MaxManifoldPressure_inHg;
-    else if (token == "DISPLACEMENT") *Eng_cfg >> Displacement;
-    else if (token == "MAXHP") *Eng_cfg >> MaxHP;
-    else if (token == "CYCLES") *Eng_cfg >> Cycles;
-    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
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPiston::~FGPiston()
-{
-  Debug(1); // Call Debug() routine from constructor if needed
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGPiston::Calculate(void)
-{
-  if (FuelFlow_gph > 0.0) ConsumeFuel();
-
-  Throttle = FCS->GetThrottlePos(EngineNumber);
-  Mixture = FCS->GetMixturePos(EngineNumber);
-
-  //
-  // Input values.
-  //
-
-  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 = Thruster->GetRPM() * Thruster->GetGearRatio();
-
-  IAS = Auxiliary->GetVcalibratedKTS();
-
-  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
-  //This might be a bit generous, but since there's currently no audiable warning of impending
-  //cutout in the form of misfiring and/or rough running its probably reasonable for now.
-  if (equivalence_ratio < 0.668)
-    Running = false;
-
-  doEnginePower();
-  doEGT();
-  doCHT();
-  doOilTemperature();
-  doOilPressure();
-
-  if (Thruster->GetType() == FGThruster::ttPropeller) {
-    ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
-  }
-
-  PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
-
-  return Thrust = Thruster->Calculate(PowerAvailable);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Start or stop the engine.
- */
-
-void FGPiston::doEngineStartup(void)
-{
-  // Check parameters that may alter the operating state of the engine.
-  // (spark, fuel, starter motor etc)
-  bool spark;
-  bool fuel;
-
-  // Check for spark
-  Magneto_Left = false;
-  Magneto_Right = false;
-  // Magneto positions:
-  // 0 -> off
-  // 1 -> left only
-  // 2 -> right only
-  // 3 -> both
-  if (Magnetos != 0) {
-    spark = true;
-  } 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;
-
-  // Assume we have fuel for now
-  fuel = !Starved;
-
-  // Check if we are turning the starter motor
-  if (Cranking != Starter) {
-    // This check saves .../cranking from getting updated every loop - they
-    // only update when changed.
-    Cranking = Starter;
-    crank_counter = 0;
-  }
-
-  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
-        Running = true;                         // on the starter
-    } else {
-      if (RPM > 450)                            // This allows us to in-air start
-        Running = true;                         // when windmilling
-    }
-  }
-
-  // Cut the engine *power* - Note: the engine may continue to
-  // spin if the prop is in a moving airstream
-
-  if ( Running && (!spark || !fuel) ) Running = false;
-
-  // Check for stalling (RPM = 0).
-  if (Running) {
-    if (RPM == 0) {
-      Running = false;
-    } else if ((RPM <= 480) && (Cranking)) {
-      Running = false;
-    }
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-/**
- * Calculate the Current Boost Speed
- *
- * 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: minMAP, maxMAP, p_amb, Throttle
- *
- * Outputs: MAP, ManifoldPressure_inHg
- */
-
-void FGPiston::doMAP(void)
-{
-  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 {
-    // 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).
- *
- * 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 = 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;
-  m_dot_air = v_dot_air * rho_air_manifold;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the fuel flow into the engine.
- *
- * Inputs: Mixture, thi_sea_level, p_amb_sea_level, p_amb, m_dot_air
- *
- * Outputs: equivalence_ratio, m_dot_fuel
- */
-
-void FGPiston::doFuelFlow(void)
-{
-  double thi_sea_level = 1.3 * Mixture;
-  equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb;
-  m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio;
-  FuelFlow_gph = m_dot_fuel
-    * 3600                     // seconds to hours
-    * 2.2046                   // kg to lb
-    / 6.6;                     // lb to gal_us of kerosene
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the power produced by the engine.
- *
- * Currently, the JSBSim propellor model does not allow the
- * engine to produce enough RPMs to get up to a high horsepower.
- * When tested with sufficient RPM, it has no trouble reaching
- * 200HP.
- *
- * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb,
- *   equivalence_ratio, Cycles, MaxHP
- *
- * Outputs: Percentage_Power, HP
- */
-
-void FGPiston::doEnginePower(void)
-{
-  if (Running) {
-    double T_amb_degF = KelvinToFahrenheit(T_amb);
-    double T_amb_sea_lev_degF = KelvinToFahrenheit(288);
-
-    // FIXME: this needs to be generalized
-    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(Boosted) {
-      HP = Percentage_Power * RatedPower[BoostSpeed] / 100.0;
-    } else {
-      HP = Percentage_Power * MaxHP / 100.0;
-    }
-
-  } else {
-
-    // Power output when the engine is not running
-    if (Cranking) {
-      if (RPM < 10) {
-        HP = 3.0;   // This is a hack to prevent overshooting the idle rpm in
-                    // 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);
-        // This is a guess - would be nice to find a proper starter moter torque curve
-      } else {
-        HP = 3.0;
-      }
-    } else {
-      // Quick hack until we port the FMEP stuff
-      if (RPM > 0.0)
-        HP = -1.5;
-      else
-        HP = 0.0;
-    }
-  }
-  //cout << "Power = " << HP << '\n';
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the exhaust gas temperature.
- *
- * 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
- */
-
-void FGPiston::doEGT(void)
-{
-  double delta_T_exhaust;
-  double enthalpy_exhaust;
-  double heat_capacity_exhaust;
-  double dEGTdt;
-
-  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 *
-                              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;
-    ExhaustGasTemp_degK = T_amb + delta_T_exhaust;
-    ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * Percentage_Power / 100.0);
-  } else {  // Drop towards ambient - guess an appropriate time constant for now
-    dEGTdt = (298.0 - ExhaustGasTemp_degK) / 100.0;
-    delta_T_exhaust = dEGTdt * dt;
-    ExhaustGasTemp_degK += delta_T_exhaust;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the cylinder head temperature.
- *
- * Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel,
- *   combustion_efficiency, RPM
- *
- * Outputs: CylinderHeadTemp_degK
- */
-
-void FGPiston::doCHT(void)
-{
-  double h1 = -95.0;
-  double h2 = -3.95;
-  double h3 = -0.05;
-
-  double arbitary_area = 1.0;
-  double CpCylinderHead = 800.0;
-  double MassCylinderHead = 8.0;
-
-  double temperature_difference = CylinderHeadTemp_degK - T_amb;
-  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 =
-    m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;
-  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;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the oil temperature.
- *
- * Inputs: Percentage_Power, running flag.
- *
- * Outputs: OilTemp_degK
- */
-
-void FGPiston::doOilTemperature(void)
-{
-  double idle_percentage_power = 2.3;        // approximately
-  double target_oil_temp;        // Steady state oil temp at the current engine conditions
-  double time_constant;          // The time constant for the differential equation
-
-  if (Running) {
-    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
-    }
-  } else {
-    target_oil_temp = 298;
-    time_constant = 1000;  // Time constant for engine-off; reflects the fact
-                           // that oil is no longer getting circulated
-  }
-
-  double dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant;
-
-  OilTemp_degK += (dOilTempdt * dt);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the oil pressure.
- *
- * Inputs: RPM
- *
- * Outputs: OilPressure_psi
- */
-
-void FGPiston::doOilPressure(void)
-{
-  double Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine
-  double Oil_Press_RPM_Max = 1800;    // FIXME: may vary by engine
-  double Design_Oil_Temp = 358;              // degK; FIXME: may vary by engine
-  double Oil_Viscosity_Index = 0.25;
-
-  OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM;
-
-  if (OilPressure_psi >= Oil_Press_Relief_Valve) {
-    OilPressure_psi = Oil_Press_Relief_Valve;
-  }
-
-  OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPiston::GetEngineLabels(string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << Name << "_PwrAvail[" << EngineNumber << "]" << delimeter
-      << Name << "_HP[" << EngineNumber << "]" << delimeter
-      << Name << "_equiv_ratio[" << EngineNumber << "]" << delimeter
-      << Name << "_MAP[" << EngineNumber << "]" << delimeter
-      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPiston::GetEngineValues(string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << PowerAvailable << delimeter << HP << delimeter
-      << equivalence_ratio << delimeter << MAP << delimeter
-      << Thruster->GetThrusterValues(EngineNumber, delimeter);
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//
-//    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 FGPiston::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 << "      MinManifoldPressure: " << MinManifoldPressure_inHg << endl;
-      cout << "      MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl;
-      cout << "      Displacement: "        << Displacement             << endl;
-      cout << "      MaxHP: "               << MaxHP                    << endl;
-      cout << "      Cycles: "              << Cycles                   << endl;
-      cout << "      IdleRPM: "             << IdleRPM                  << endl;
-      cout << "      MaxThrottle: "         << MaxThrottle              << endl;
-      cout << "      MinThrottle: "         << MinThrottle              << endl;
-
-      cout << endl;
-      cout << "      Combustion Efficiency table:" << endl;
-      Lookup_Combustion_Efficiency->Print();
-      cout << endl;
-
-      cout << endl;
-      cout << "      Power Mixture Correlation table:" << endl;
-      Power_Mixture_Correlation->Print();
-      cout << endl;
-
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGPiston" << endl;
-    if (from == 1) cout << "Destroyed:    FGPiston" << 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
-FGPiston::CalcFuelNeed(void)
-{
-  return FuelFlow_gph / 3600 * 6 * State->Getdt() * Propulsion->GetRate();
-}
-
-} // namespace JSBSim
diff --git a/src/FDM/JSBSim/FGPiston.h b/src/FDM/JSBSim/FGPiston.h
deleted file mode 100644 (file)
index 7039aa4..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGPiston.h
- Author:       Jon S. Berndt
- Date started: 09/12/2000
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-09/12/2000  JSB  Created
-10/01/2001  DPM  Modified to use equations from Dave Luff's piston model.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGPISTON_H
-#define FGPISTON_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGEngine.h"
-#include "FGConfigFile.h"
-#include "FGTable.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_PISTON "$Id$";
-#define FG_MAX_BOOST_SPEEDS 3
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** 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 (initial porting and additional code)
-    @version $Id$
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGPiston : public FGEngine
-{
-public:
-  /// Constructor
-  FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number);
-  /// Destructor
-  ~FGPiston();
-
-  string GetEngineLabels(string delimeter);
-  string GetEngineValues(string delimeter);
-
-  double Calculate(void);
-  double GetPowerAvailable(void) {return PowerAvailable;}
-  double CalcFuelNeed(void);
-
-  void SetMagnetos(int magnetos) {Magnetos = magnetos;}
-
-  double  GetEGT(void) { return EGT_degC; }
-  int     GetMagnetos(void) {return Magnetos;}
-
-  double getExhaustGasTemp_degF(void) {return KelvinToFahrenheit(ExhaustGasTemp_degK);}
-  double getManifoldPressure_inHg(void) const {return ManifoldPressure_inHg;}
-  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;}
-
-private:
-  int crank_counter;
-
-  double BrakeHorsePower;
-  double SpeedSlope;
-  double SpeedIntercept;
-  double AltitudeSlope;
-  double PowerAvailable;
-
-  // timestep
-  double dt;
-
-  void doEngineStartup(void);
-  void doBoostControl(void);
-  void doMAP(void);
-  void doAirFlow(void);
-  void doFuelFlow(void);
-  void doEnginePower(void);
-  void doEGT(void);
-  void doCHT(void);
-  void doOilPressure(void);
-  void doOilTemperature(void);
-
-  //
-  // constants
-  //
-
-  const double R_air;
-  const double rho_fuel;    // kg/m^3
-  const double calorific_value_fuel;  // W/Kg (approximate)
-  const double Cp_air;      // J/KgK
-  const double Cp_fuel;     // J/KgK
-
-  FGTable *Lookup_Combustion_Efficiency;
-  FGTable *Power_Mixture_Correlation;
-
-  //
-  // Configuration
-  //
-  double MinManifoldPressure_inHg; // Inches Hg
-  double MaxManifoldPressure_inHg; // Inches Hg
-  double Displacement;             // cubic inches
-  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).
-  //
-  double p_amb;              // Pascals
-  double p_amb_sea_level;    // Pascals
-  double T_amb;              // degrees Kelvin
-  double RPM;                // revolutions per minute
-  double IAS;                // knots
-  bool Magneto_Left;
-  bool Magneto_Right;
-  int Magnetos;
-
-  //
-  // Outputs (in addition to those in FGEngine).
-  //
-  double rho_air;
-  double volumetric_efficiency;
-  double m_dot_air;
-  double equivalence_ratio;
-  double m_dot_fuel;
-  double Percentage_Power;
-  double HP;
-  double combustion_efficiency;
-  double ExhaustGasTemp_degK;
-  double EGT_degC;
-  double ManifoldPressure_inHg;
-  double CylinderHeadTemp_degK;
-  double OilPressure_psi;
-  double OilTemp_degK;
-
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
diff --git a/src/FDM/JSBSim/FGPropagate.cpp b/src/FDM/JSBSim/FGPropagate.cpp
deleted file mode 100644 (file)
index 4d5d677..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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 HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#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 = SeaLevelRadius;
-
-  // 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;
-
-  // Finaly make shure that the quaternion stays normalized.
-  VState.vQtrn.Normalize();
-
-  // Recompute the RunwayRadius level.
-  RecomputeRunwayRadius();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/*
-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 ...
-
-  RecomputeRunwayRadius();
-
-  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;
-
-  // Coriolis acceleration.
-  FGColumnVector3 ecVel = Tl2ec*vVel;
-  FGColumnVector3 ace = 2.0*omega*ecVel;
-  vUVWdot -= Tl2b*(Tec2l*ace);
-
-  // Centrifugal 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::RecomputeRunwayRadius(void)
-{
-  // Get the runway radius.
-  // Boring: this does not belong here, but since Jon placed the RunwayRadius
-  // value here it is better done here than somewhere else.
-  FGLocation contactloc;
-  FGColumnVector3 dv;
-  FGGroundCallback* gcb = FDMExec->GetGroundCallback();
-  double t = State->Getsim_time();
-  gcb->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
-  RunwayRadius = contactloc.GetRadius();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropagate::Seth(double tt)
-{
-  VState.vLocation.SetRadius( tt + SeaLevelRadius );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGPropagate::GetRunwayRadius(void) const
-{
-  return RunwayRadius;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGPropagate::GetDistanceAGL(void) const
-{
-  return VState.vLocation.GetRadius() - RunwayRadius;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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);
-
-  PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
-  PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
-  PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
-
-  PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
-  PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
-  PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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
deleted file mode 100644 (file)
index b778bb0..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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 GetCosEuler(int idx) const { return VState.vQtrn.GetCosEuler(idx); }
-  double GetSinEuler(int idx) const { return VState.vQtrn.GetSinEuler(idx); }
-  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;
-  double GetSeaLevelRadius(void) const { return SeaLevelRadius; }
-  double GetDistanceAGL(void)  const;
-  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; }
-
-  /** 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 SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
-  void SetDistanceAGL(double tt);
-  void SetInitialState(const FGInitialCondition *);
-
-  void RecomputeRunwayRadius(void);
-
-  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
diff --git a/src/FDM/JSBSim/FGPropeller.cpp b/src/FDM/JSBSim/FGPropeller.cpp
deleted file mode 100644 (file)
index 6ef0f53..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGPropeller.cpp
- Author:       Jon S. Berndt
- Date started: 08/24/00
- Purpose:      Encapsulates the propeller object
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/24/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <sstream>
-
-#include "FGPropeller.h"
-#include "FGPropagate.h"
-#include "FGAtmosphere.h"
-#include "FGAuxiliary.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_PROPELLER;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-// 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
-// helicopter.
-
-FGPropeller::FGPropeller(FGFDMExec* exec, FGConfigFile* Prop_cfg, int num) : FGThruster(exec)
-{
-  string token;
-  int rows, cols;
-
-  MaxPitch = MinPitch = P_Factor = Sense = Pitch = Advance = 0.0;
-  GearRatio = 1.0;
-
-  Name = Prop_cfg->GetValue("NAME");
-  Prop_cfg->GetNextConfigLine();
-  while (Prop_cfg->GetValue() != string("/FG_PROPELLER")) {
-    *Prop_cfg >> token;
-    if (token == "IXX") {
-      *Prop_cfg >> Ixx;
-    } else if (token == "DIAMETER") {
-      *Prop_cfg >> Diameter;
-      Diameter /= 12.0;
-    } else if (token == "NUMBLADES") {
-      *Prop_cfg >> numBlades;
-    } else if (token == "GEARRATIO") {
-      *Prop_cfg >> GearRatio;
-    } else if (token == "MINPITCH") {
-      *Prop_cfg >> MinPitch;
-    } else if (token == "MAXPITCH") {
-      *Prop_cfg >> MaxPitch;
-    } else if (token == "MINRPM") {
-      *Prop_cfg >> MinRPM;
-    } else if (token == "MAXRPM") {
-      *Prop_cfg >> MaxRPM;
-    } else if (token == "C_THRUST") {
-      *Prop_cfg >> rows >> cols;
-      if (cols == 1) cThrust = new FGTable(rows);
-      else           cThrust = new FGTable(rows, cols);
-      *cThrust << *Prop_cfg;
-    } else if (token == "C_POWER") {
-      *Prop_cfg >> rows >> cols;
-      if (cols == 1) cPower = new FGTable(rows);
-      else           cPower = new FGTable(rows, cols);
-      *cPower << *Prop_cfg;
-    } else if (token == "EOF") {
-      cerr << "      End of file reached" <<  endl;
-      break;
-    } else {
-      cerr << "Unhandled token in Propeller config file: " << token << endl;
-    }
-  }
-
-  Type = ttPropeller;
-  RPM = 0;
-  vTorque.InitMatrix();
-
-  char property_name[80];
-  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
-  PropertyManager->Tie( property_name, &ThrustCoeff );
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPropeller::~FGPropeller()
-{
-  if (cThrust)    delete cThrust;
-  if (cPower)     delete cPower;
-
-  char property_name[80];
-  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
-  PropertyManager->Untie( property_name );
-
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//
-// We must be getting the aerodynamic velocity here, NOT the inertial velocity.
-// We need the velocity with respect to the wind.
-//
-// Note that PowerAvailable is the excess power available after the drag of the
-// propeller has been subtracted. At equilibrium, PowerAvailable will be zero -
-// indicating that the propeller will not accelerate or decelerate.
-// Remembering that Torque * omega = Power, we can derive the torque on the
-// propeller and its acceleration to give a new RPM. The current RPM will be
-// used to calculate thrust.
-//
-// Because RPM could be zero, we need to be creative about what RPM is stated as.
-
-double FGPropeller::Calculate(double PowerAvailable)
-{
-  double J, omega;
-  double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU);
-  double rho = fdmex->GetAtmosphere()->GetDensity();
-  double RPS = RPM/60.0;
-  double alpha, beta;
-
-  if (RPM > 0.10) {
-    J = Vel / (Diameter * RPS);
-  } else {
-    J = 0.0;
-  }
-
-  if (MaxPitch == MinPitch) { // Fixed pitch prop
-    ThrustCoeff = cThrust->GetValue(J);
-  } else {                    // Variable pitch prop
-    ThrustCoeff = cThrust->GetValue(J, Pitch);
-  }
-
-  if (P_Factor > 0.0001) {
-    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) {
-    cerr << "P-Factor value in config file must be greater than zero" << endl;
-  }
-
-  Thrust = ThrustCoeff*RPS*RPS*Diameter*Diameter*Diameter*Diameter*rho;
-  omega = RPS*2.0*M_PI;
-
-  vFn(1) = Thrust;
-
-  // The Ixx value and rotation speed given below are for rotation about the
-  // natural axis of the engine. The transform takes place in the base class
-  // FGForce::GetBodyForces() function.
-
-  vH(eX) = Ixx*omega*Sense;
-  vH(eY) = 0.0;
-  vH(eZ) = 0.0;
-
-  if (omega <= 5) omega = 1.0;
-
-  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.
-  if (RPM < 5.0)
-    RPM = 0;
-
-  vMn = fdmex->GetPropagate()->GetPQR()*vH + vTorque*Sense;
-
-  return Thrust; // return thrust in pounds
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGPropeller::GetPowerRequired(void)
-{
-  if (RPM <= 0.10) return 0.0; // If the prop ain't turnin', the fuel ain't burnin'.
-
-  double cPReq, RPS = RPM / 60.0;
-
-  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
-
-    if (MaxRPM != MinRPM) {   // fixed-speed prop
-      double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
-      double dRPM = rpmReq - RPM;
-
-      Pitch -= dRPM / 10;
-
-      if (Pitch < MinPitch)       Pitch = MinPitch;
-      else if (Pitch > MaxPitch)  Pitch = MaxPitch;
-
-    } else {
-      Pitch = MinPitch + (MaxPitch - MinPitch) * Advance;
-    }
-    cPReq = cPower->GetValue(J, Pitch);
-  }
-
-  PowerRequired = cPReq*RPS*RPS*RPS*Diameter*Diameter*Diameter*Diameter
-                                                       *Diameter*rho;
-  vTorque(eX) = -Sense*PowerRequired / (RPS*2.0*M_PI);
-
-  return PowerRequired;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector3 FGPropeller::GetPFactor()
-{
-  double px=0.0, py, pz;
-
-  py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0;
-  pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0;
-
-  return FGColumnVector3(px, py, pz);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropeller::GetThrusterLabels(int id, string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << Name << "_Torque[" << id << "]" << delimeter
-      << Name << "_PFactor_Pitch[" << id << "]" << delimeter
-      << Name << "_PFactor_Yaw[" << id << "]" << delimeter
-      << Name << "_Thrust[" << id << "]" << delimeter;
-  if (IsVPitch())
-    buf << Name << "_Pitch[" << id << "]" << delimeter;
-  buf << Name << "_RPM[" << id << "]";
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropeller::GetThrusterValues(int id, string delimeter)
-{
-  std::ostringstream buf;
-
-  FGColumnVector3 vPFactor = GetPFactor();
-  buf << vTorque(eX) << delimeter
-      << vPFactor(ePitch) << delimeter
-      << vPFactor(eYaw) << delimeter
-      << Thrust << delimeter;
-  if (IsVPitch())
-    buf << Pitch << delimeter;
-  buf << RPM;
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGPropeller::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "\n    Propeller Name: " << Name << endl;
-      cout << "      IXX = " << Ixx << endl;
-      cout << "      Diameter = " << Diameter << " ft." << endl;
-      cout << "      Number of Blades  = " << numBlades << endl;
-      cout << "      Minimum Pitch  = " << MinPitch << endl;
-      cout << "      Maximum Pitch  = " << MaxPitch << endl;
-      cout << "      Thrust Coefficient: " <<  endl;
-      cThrust->Print();
-      cout << "      Power Coefficient: " <<  endl;
-      cPower->Print();
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGPropeller" << endl;
-    if (from == 1) cout << "Destroyed:    FGPropeller" << 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/FGPropeller.h b/src/FDM/JSBSim/FGPropeller.h
deleted file mode 100644 (file)
index 0434e69..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGPropeller.h
- Author:       Jon S. Berndt
- Date started: 08/24/00
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/24/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGPROPELLER_H
-#define FGPROPELLER_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGThruster.h"
-#include "FGTable.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_PROPELLER "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Propeller modeling class.
-    FGPropeller models a propeller given the tabular data for Ct and Cp
-    indexed by advance ratio "J". The data for the propeller is
-    stored in a config file named "prop_name.xml". The propeller config file
-    is referenced from the main aircraft config file in the "Propulsion" section.
-    See the constructor for FGPropeller to see what is read in and what should
-    be stored in the config file.<br>
-    Several references were helpful, here:<ul>
-    <li>Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
-     Wiley & Sons, 1979 ISBN 0-471-03032-5</li>
-    <li>Edwin Hartman, David Biermann, "The Aerodynamic Characteristics of
-    Full Scale Propellers Having 2, 3, and 4 Blades of Clark Y and R.A.F. 6
-    Airfoil Sections", NACA Report TN-640, 1938 (?)</li>
-    <li>Various NACA Technical Notes and Reports</li>
-    </ul>
-    @author Jon S. Berndt
-    @version $Id$
-    @see FGEngine
-    @see FGThruster
-    @see FGTable
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGPropeller : public FGThruster {
-
-public:
-  /** Constructor for FGPropeller.
-      @param exec a pointer to the main executive object
-      @param AC_cfg a pointer to the main aircraft config file object */
-  FGPropeller(FGFDMExec* exec, FGConfigFile* AC_cfg, int num = 0);
-
-  /// Destructor for FGPropeller - deletes the FGTable objects
-  ~FGPropeller();
-
-  /** Sets the Revolutions Per Minute for the propeller. Normally the propeller
-      instance will calculate its own rotational velocity, given the Torque
-      produced by the engine and integrating over time using the standard
-      equation for rotational acceleration "a": a = Q/I , where Q is Torque and
-      I is moment of inertia for the propeller.
-      @param rpm the rotational velocity of the propeller */
-  void SetRPM(double rpm) {RPM = rpm;}
-
-  /// Returns true of this propeller is variable pitch
-  bool IsVPitch(void) {return MaxPitch != MinPitch;}
-
-  /** This commands the pitch of the blade to change to the value supplied.
-      This call is meant to be issued either from the cockpit or by the flight
-      control system (perhaps to maintain constant RPM for a constant-speed
-      propeller). This value will be limited to be within whatever is specified
-      in the config file for Max and Min pitch. It is also one of the lookup
-      indices to the power and thrust tables for variable-pitch propellers.
-      @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;}
-
-  /** Sets the rotation sense of the propeller.
-      @param s this value should be +/- 1 ONLY. +1 indicates clockwise rotation as
-               viewed by someone standing behind the engine looking forward into
-               the direction of flight. */
-  void SetSense(double s) { Sense = s;}
-
-  double GetSense(void) {return Sense;}
-  double GetPFactorValue(void) {return P_Factor;}
-
-  /// 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
-      the torque provided by the engine over what the propeller "absorbs"
-      (essentially the "drag" of the propeller).
-      @param PowerAvailable this is the excess power provided by the engine to
-      accelerate the prop. It could be negative, dictating that the propeller
-      would be slowed.
-      @return the thrust in pounds */
-  double Calculate(double PowerAvailable);
-  FGColumnVector3 GetPFactor(void);
-  string GetThrusterLabels(int id, string delimeter);
-  string GetThrusterValues(int id, string delimeter);
-
-private:
-  int   numBlades;
-  double RPM;
-  double Ixx;
-  double Diameter;
-  double MaxPitch;
-  double MinPitch;
-  double MinRPM;
-  double MaxRPM;
-  double P_Factor;
-  double Sense;
-  double Pitch;
-  double Advance;
-  double ExcessTorque;
-  FGColumnVector3 vTorque;
-  FGTable *cThrust;
-  FGTable *cPower;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGPropertyManager.cpp b/src/FDM/JSBSim/FGPropertyManager.cpp
deleted file mode 100644 (file)
index 42d632d..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGPropertyManager.cpp
- Author:       Tony Peden
-               Based on work originally by David Megginson
- Date:         2/2002
-
- ------------- Copyright (C) 2002 -------------
-
- 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.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGPropertyManager.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-using namespace std;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*/
-
-namespace JSBSim {
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
-
-  /* do this two pass to avoid problems with characters getting skipped
-     because the index changed */
-  unsigned i;
-  for(i=0;i<name.length();i++) {
-    if( lowercase && isupper(name[i]) )
-      name[i]=tolower(name[i]);
-    else if( isspace(name[i]) )
-      name[i]='-';
-  }
-  for(i=0;i<name.length();i++) {
-    if( name[i] == '/' )
-      name.erase(i,1);
-  }
-
-  return name;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPropertyManager*
-FGPropertyManager::GetNode (const string &path, bool create)
-{
-  SGPropertyNode* node=this->getNode(path.c_str(), create);
-  //if(node == 0)
-  //  cout << "FGPropertyManager::GetNode() No node found for "
-  //       << path << endl;
-  return (FGPropertyManager*)node;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPropertyManager*
-FGPropertyManager::GetNode (const string &relpath, int index, bool create)
-{
-    return (FGPropertyManager*)getNode(relpath.c_str(),index,create);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-bool FGPropertyManager::HasNode (const string &path)
-{
-  return (GetNode(path, false) != 0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropertyManager::GetName( void ) {
-  return string( getName() );
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropertyManager::GetFullyQualifiedName(void) {
-    vector<string> stack;
-    stack.push_back( getDisplayName(true) );
-    SGPropertyNode* tmpn=getParent();
-    bool atroot=false;
-    while( !atroot ) {
-     stack.push_back( tmpn->getDisplayName(true) );
-     if( !tmpn->getParent() )
-      atroot=true;
-     else
-      tmpn=tmpn->getParent();
-    }
-
-    string fqname="";
-    for(unsigned i=stack.size()-1;i>0;i--) {
-      fqname+= stack[i];
-      fqname+= "/";
-    }
-    fqname+= stack[0];
-    return fqname;
-
-}
-
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropertyManager::GetBool (const string &name, bool defaultValue)
-{
-  return getBoolValue(name.c_str(), defaultValue);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-int FGPropertyManager::GetInt (const string &name, int defaultValue )
-{
-  return getIntValue(name.c_str(), defaultValue);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-int FGPropertyManager::GetLong (const string &name, long defaultValue )
-{
-  return getLongValue(name.c_str(), defaultValue);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-float FGPropertyManager::GetFloat (const string &name, float defaultValue )
-{
-  return getFloatValue(name.c_str(), defaultValue);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGPropertyManager::GetDouble (const string &name, double defaultValue )
-{
-  return getDoubleValue(name.c_str(), defaultValue);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropertyManager::GetString (const string &name, string defaultValue )
-{
-  return string(getStringValue(name.c_str(), defaultValue.c_str()));
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropertyManager::SetBool (const string &name, bool val)
-{
-  return setBoolValue(name.c_str(), val);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropertyManager::SetInt (const string &name, int val)
-{
-  return setIntValue(name.c_str(), val);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropertyManager::SetLong (const string &name, long val)
-{
-  return setLongValue(name.c_str(), val);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropertyManager::SetFloat (const string &name, float val)
-{
-  return setFloatValue(name.c_str(), val);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropertyManager::SetDouble (const string &name, double val)
-{
-  return setDoubleValue(name.c_str(), val);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropertyManager::SetString (const string &name, const string &val)
-{
-  return setStringValue(name.c_str(), val.c_str());
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::SetArchivable (const string &name, bool state )
-{
-  SGPropertyNode * node = getNode(name.c_str());
-  if (node == 0)
-    cout <<
-           "Attempt to set archive flag for non-existant property "
-           << name << endl;
-  else
-    node->setAttribute(SGPropertyNode::ARCHIVE, state);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::SetReadable (const string &name, bool state )
-{
-  SGPropertyNode * node = getNode(name.c_str());
-  if (node == 0)
-    cout <<
-           "Attempt to set read flag for non-existant property "
-           << name << endl;
-  else
-    node->setAttribute(SGPropertyNode::READ, state);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::SetWritable (const string &name, bool state )
-{
-  SGPropertyNode * node = getNode(name.c_str());
-  if (node == 0)
-    cout <<
-           "Attempt to set write flag for non-existant property "
-           << name << endl;
-  else
-    node->setAttribute(SGPropertyNode::WRITE, state);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Untie (const string &name)
-{
-  if (!untie(name.c_str()))
-    cout << "Failed to untie property " << name << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
-{
-  if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer),
-                                 useDefault))
-    cout <<
-           "Failed to tie property " << name << " to a pointer" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, int *pointer,
-                                          bool useDefault )
-{
-  if (!tie(name.c_str(), SGRawValuePointer<int>(pointer),
-                                 useDefault))
-    cout <<
-           "Failed to tie property " << name << " to a pointer" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, long *pointer,
-                                          bool useDefault )
-{
-  if (!tie(name.c_str(), SGRawValuePointer<long>(pointer),
-                                 useDefault))
-    cout <<
-           "Failed to tie property " << name << " to a pointer" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, float *pointer,
-                                          bool useDefault )
-{
-  if (!tie(name.c_str(), SGRawValuePointer<float>(pointer),
-                                 useDefault))
-    cout <<
-           "Failed to tie property " << name << " to a pointer" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, double *pointer,
-                                           bool useDefault)
-{
-  if (!tie(name.c_str(), SGRawValuePointer<double>(pointer),
-                                 useDefault))
-    cout <<
-           "Failed to tie property " << name << " to a pointer" << endl;
-}
-
-} // namespace JSBSim
diff --git a/src/FDM/JSBSim/FGPropertyManager.h b/src/FDM/JSBSim/FGPropertyManager.h
deleted file mode 100644 (file)
index e257e9b..0000000
+++ /dev/null
@@ -1,611 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGPropertyManager.h
- Author:       Tony Peden
-               Based on work originally by David Megginson
- Date:         2/2002
-
- ------------- Copyright (C) 2002 -------------
-
- 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.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGPROPERTYMANAGER_H
-#define FGPROPERTYMANAGER_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <string>
-#ifdef FGFS
-#include <simgear/props/props.hxx>
-#else
-#include "simgear/props/props.hxx"
-#endif
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_PROPERTYMANAGER "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-using namespace std;
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Class wrapper for property handling.
-    @author David Megginson, Tony Peden
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGPropertyManager : public SGPropertyNode {
-  public:
-    /// Constructor
-    FGPropertyManager(void) {}
-    /// Destructor
-    ~FGPropertyManager(void) {}
-
-    /** Property-ify a name
-     *  replaces spaces with '-' and, optionally, makes name all lower case
-     *  @param name string to change
-     *  @param lowercase true to change all upper case chars to lower
-     *  NOTE: this function changes its argument and thus relies
-     *  on pass by value
-     */
-    string mkPropertyName(string name, bool lowercase);
-
-    /**
-     * Get a property node.
-     *
-     * @param path The path of the node, relative to root.
-     * @param create true to create the node if it doesn't exist.
-     * @return The node, or 0 if none exists and none was created.
-     */
-    FGPropertyManager*
-    GetNode (const string &path, bool create = false);
-
-    FGPropertyManager*
-    GetNode (const string &relpath, int index, bool create = false);
-
-    /**
-     * Test whether a given node exists.
-     *
-     * @param path The path of the node, relative to root.
-     * @return true if the node exists, false otherwise.
-     */
-    bool HasNode (const string &path);
-
-    /**
-     * Get the name of a node
-     */
-    string GetName( void );
-
-    /**
-     * Get the fully qualified name of a node
-     * This function is very slow, so is probably useful for debugging only.
-     */
-    string GetFullyQualifiedName(void);
-
-    /**
-     * Get a bool value for a property.
-     *
-     * This method is convenient but inefficient.  It should be used
-     * infrequently (i.e. for initializing, loading, saving, etc.),
-     * not in the main loop.  If you need to get a value frequently,
-     * it is better to look up the node itself using GetNode and then
-     * use the node's getBoolValue() method, to avoid the lookup overhead.
-     *
-     * @param name The property name.
-     * @param defaultValue The default value to return if the property
-     *        does not exist.
-     * @return The property's value as a bool, or the default value provided.
-     */
-    bool GetBool (const string &name, bool defaultValue = false);
-
-
-    /**
-     * Get an int value for a property.
-     *
-     * This method is convenient but inefficient.  It should be used
-     * infrequently (i.e. for initializing, loading, saving, etc.),
-     * not in the main loop.  If you need to get a value frequently,
-     * it is better to look up the node itself using GetNode and then
-     * use the node's getIntValue() method, to avoid the lookup overhead.
-     *
-     * @param name The property name.
-     * @param defaultValue The default value to return if the property
-     *        does not exist.
-     * @return The property's value as an int, or the default value provided.
-     */
-    int GetInt (const string &name, int defaultValue = 0);
-
-
-    /**
-     * Get a long value for a property.
-     *
-     * This method is convenient but inefficient.  It should be used
-     * infrequently (i.e. for initializing, loading, saving, etc.),
-     * not in the main loop.  If you need to get a value frequently,
-     * it is better to look up the node itself using GetNode and then
-     * use the node's getLongValue() method, to avoid the lookup overhead.
-     *
-     * @param name The property name.
-     * @param defaultValue The default value to return if the property
-     *        does not exist.
-     * @return The property's value as a long, or the default value provided.
-     */
-    int GetLong (const string &name, long defaultValue = 0L);
-
-
-    /**
-     * Get a float value for a property.
-     *
-     * This method is convenient but inefficient.  It should be used
-     * infrequently (i.e. for initializing, loading, saving, etc.),
-     * not in the main loop.  If you need to get a value frequently,
-     * it is better to look up the node itself using GetNode and then
-     * use the node's getFloatValue() method, to avoid the lookup overhead.
-     *
-     * @param name The property name.
-     * @param defaultValue The default value to return if the property
-     *        does not exist.
-     * @return The property's value as a float, or the default value provided.
-     */
-    float GetFloat (const string &name, float defaultValue = 0.0);
-
-
-    /**
-     * Get a double value for a property.
-     *
-     * This method is convenient but inefficient.  It should be used
-     * infrequently (i.e. for initializing, loading, saving, etc.),
-     * not in the main loop.  If you need to get a value frequently,
-     * it is better to look up the node itself using GetNode and then
-     * use the node's getDoubleValue() method, to avoid the lookup overhead.
-     *
-     * @param name The property name.
-     * @param defaultValue The default value to return if the property
-     *        does not exist.
-     * @return The property's value as a double, or the default value provided.
-     */
-    double GetDouble (const string &name, double defaultValue = 0.0);
-
-
-    /**
-     * Get a string value for a property.
-     *
-     * This method is convenient but inefficient.  It should be used
-     * infrequently (i.e. for initializing, loading, saving, etc.),
-     * not in the main loop.  If you need to get a value frequently,
-     * it is better to look up the node itself using GetNode and then
-     * use the node's getStringValue() method, to avoid the lookup overhead.
-     *
-     * @param name The property name.
-     * @param defaultValue The default value to return if the property
-     *        does not exist.
-     * @return The property's value as a string, or the default value provided.
-     */
-    string GetString (const string &name, string defaultValue = "");
-
-
-    /**
-     * Set a bool value for a property.
-     *
-     * Assign a bool value to a property.  If the property does not
-     * yet exist, it will be created and its type will be set to
-     * BOOL; if it has a type of UNKNOWN, the type will also be set to
-     * BOOL; otherwise, the bool value will be converted to the property's
-     * type.
-     *
-     * @param name The property name.
-     * @param val The new value for the property.
-     * @return true if the assignment succeeded, false otherwise.
-     */
-    bool SetBool (const string &name, bool val);
-
-
-    /**
-     * Set an int value for a property.
-     *
-     * Assign an int value to a property.  If the property does not
-     * yet exist, it will be created and its type will be set to
-     * INT; if it has a type of UNKNOWN, the type will also be set to
-     * INT; otherwise, the bool value will be converted to the property's
-     * type.
-     *
-     * @param name The property name.
-     * @param val The new value for the property.
-     * @return true if the assignment succeeded, false otherwise.
-     */
-    bool SetInt (const string &name, int val);
-
-
-    /**
-     * Set a long value for a property.
-     *
-     * Assign a long value to a property.  If the property does not
-     * yet exist, it will be created and its type will be set to
-     * LONG; if it has a type of UNKNOWN, the type will also be set to
-     * LONG; otherwise, the bool value will be converted to the property's
-     * type.
-     *
-     * @param name The property name.
-     * @param val The new value for the property.
-     * @return true if the assignment succeeded, false otherwise.
-     */
-    bool SetLong (const string &name, long val);
-
-
-    /**
-     * Set a float value for a property.
-     *
-     * Assign a float value to a property.  If the property does not
-     * yet exist, it will be created and its type will be set to
-     * FLOAT; if it has a type of UNKNOWN, the type will also be set to
-     * FLOAT; otherwise, the bool value will be converted to the property's
-     * type.
-     *
-     * @param name The property name.
-     * @param val The new value for the property.
-     * @return true if the assignment succeeded, false otherwise.
-     */
-    bool SetFloat (const string &name, float val);
-
-
-    /**
-     * Set a double value for a property.
-     *
-     * Assign a double value to a property.  If the property does not
-     * yet exist, it will be created and its type will be set to
-     * DOUBLE; if it has a type of UNKNOWN, the type will also be set to
-     * DOUBLE; otherwise, the double value will be converted to the property's
-     * type.
-     *
-     * @param name The property name.
-     * @param val The new value for the property.
-     * @return true if the assignment succeeded, false otherwise.
-     */
-    bool SetDouble (const string &name, double val);
-
-
-    /**
-     * Set a string value for a property.
-     *
-     * Assign a string value to a property.  If the property does not
-     * yet exist, it will be created and its type will be set to
-     * STRING; if it has a type of UNKNOWN, the type will also be set to
-     * STRING; otherwise, the string value will be converted to the property's
-     * type.
-     *
-     * @param name The property name.
-     * @param val The new value for the property.
-     * @return true if the assignment succeeded, false otherwise.
-     */
-    bool SetString (const string &name, const string &val);
-
-
-    ////////////////////////////////////////////////////////////////////////
-    // Convenience functions for setting property attributes.
-    ////////////////////////////////////////////////////////////////////////
-
-
-    /**
-     * Set the state of the archive attribute for a property.
-     *
-     * If the archive attribute is true, the property will be written
-     * when a flight is saved; if it is false, the property will be
-     * skipped.
-     *
-     * A warning message will be printed if the property does not exist.
-     *
-     * @param name The property name.
-     * @param state The state of the archive attribute (defaults to true).
-     */
-    void SetArchivable (const string &name, bool state = true);
-
-
-    /**
-     * Set the state of the read attribute for a property.
-     *
-     * If the read attribute is true, the property value will be readable;
-     * if it is false, the property value will always be the default value
-     * for its type.
-     *
-     * A warning message will be printed if the property does not exist.
-     *
-     * @param name The property name.
-     * @param state The state of the read attribute (defaults to true).
-     */
-    void SetReadable (const string &name, bool state = true);
-
-
-    /**
-     * Set the state of the write attribute for a property.
-     *
-     * If the write attribute is true, the property value may be modified
-     * (depending on how it is tied); if the write attribute is false, the
-     * property value may not be modified.
-     *
-     * A warning message will be printed if the property does not exist.
-     *
-     * @param name The property name.
-     * @param state The state of the write attribute (defaults to true).
-     */
-    void SetWritable (const string &name, bool state = true);
-
-
-    ////////////////////////////////////////////////////////////////////////
-    // Convenience functions for tying properties, with logging.
-    ////////////////////////////////////////////////////////////////////////
-
-
-    /**
-     * Untie a property from an external data source.
-     *
-     * Classes should use this function to release control of any
-     * properties they are managing.
-     */
-    void Untie (const string &name);
-
-
-        // Templates cause ambiguity here
-
-    /**
-     * Tie a property to an external bool variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const string &name, bool *pointer, bool useDefault = true);
-
-
-    /**
-     * Tie a property to an external int variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const string &name, int *pointer, bool useDefault = true);
-
-
-    /**
-     * Tie a property to an external long variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const string &name, long *pointer, bool useDefault = true);
-
-
-    /**
-     * Tie a property to an external float variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const string &name, float *pointer, bool useDefault = true);
-
-    /**
-     * Tie a property to an external double variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const string &name, double *pointer, bool useDefault = true);
-
-//============================================================================
-//
-//  All of the following functions *must* be inlined, otherwise linker
-//  errors will result
-//
-//============================================================================
-
-    /* template <class V> void
-    Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
-           bool useDefault = true);
-
-    template <class V> void
-    Tie (const string &name, int index, V (*getter)(int),
-           void (*setter)(int, V) = 0, bool useDefault = true);
-
-    template <class T, class V> void
-    Tie (const string &name, T * obj, V (T::*getter)() const,
-           void (T::*setter)(V) = 0, bool useDefault = true);
-
-    template <class T, class V> void
-    Tie (const string &name, T * obj, int index,
-           V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
-           bool useDefault = true); */
-
-     /**
-     * Tie a property to a pair of simple functions.
-     *
-     * Every time the property value is queried, the getter (if any) will
-     * be invoked; every time the property value is modified, the setter
-     * (if any) will be invoked.  The getter can be 0 to make the property
-     * unreadable, and the setter can be 0 to make the property
-     * unmodifiable.
-     *
-     * @param name The property name to tie (full path).
-     * @param getter The getter function, or 0 if the value is unreadable.
-     * @param setter The setter function, or 0 if the value is unmodifiable.
-     * @param useDefault true if the setter should be invoked with any existing
-     *        property value should be; false if the old value should be
-     *        discarded; defaults to true.
-     */
-
-    template <class V> inline void
-    Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
-                                              bool useDefault = true)
-    {
-      if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter),
-         useDefault))
-      {
-        cout <<
-         "Failed to tie property " << name << " to functions" << endl;
-      }
-    }
-
-
-    /**
-     * Tie a property to a pair of indexed functions.
-     *
-     * Every time the property value is queried, the getter (if any) will
-     * be invoked with the index provided; every time the property value
-     * is modified, the setter (if any) will be invoked with the index
-     * provided.  The getter can be 0 to make the property unreadable, and
-     * the setter can be 0 to make the property unmodifiable.
-     *
-     * @param name The property name to tie (full path).
-     * @param index The integer argument to pass to the getter and
-     *        setter functions.
-     * @param getter The getter function, or 0 if the value is unreadable.
-     * @param setter The setter function, or 0 if the value is unmodifiable.
-     * @param useDefault true if the setter should be invoked with any existing
-     *        property value should be; false if the old value should be
-     *        discarded; defaults to true.
-     */
-    template <class V> inline void Tie (const string &name,
-                                        int index, V (*getter)(int),
-           void (*setter)(int, V) = 0, bool useDefault = true)
-    {
-      if (!tie(name.c_str(),
-           SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
-      {
-        cout <<
-         "Failed to tie property " << name << " to indexed functions" << endl;
-      }
-    }
-
-
-    /**
-     * Tie a property to a pair of object methods.
-     *
-     * Every time the property value is queried, the getter (if any) will
-     * be invoked; every time the property value is modified, the setter
-     * (if any) will be invoked.  The getter can be 0 to make the property
-     * unreadable, and the setter can be 0 to make the property
-     * unmodifiable.
-     *
-     * @param name The property name to tie (full path).
-     * @param obj The object whose methods should be invoked.
-     * @param getter The object's getter method, or 0 if the value is
-     *        unreadable.
-     * @param setter The object's setter method, or 0 if the value is
-     *        unmodifiable.
-     * @param useDefault true if the setter should be invoked with any existing
-     *        property value should be; false if the old value should be
-     *        discarded; defaults to true.
-     */
-    template <class T, class V> inline void
-    Tie (const string &name, T * obj, V (T::*getter)() const,
-           void (T::*setter)(V) = 0, bool useDefault = true)
-    {
-      if (!tie(name.c_str(),
-             SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
-      {
-        cout <<
-         "Failed to tie property " << name << " to object methods" << endl;
-      }
-    }
-
-    /**
-     * Tie a property to a pair of indexed object methods.
-     *
-     * Every time the property value is queried, the getter (if any) will
-     * be invoked with the index provided; every time the property value
-     * is modified, the setter (if any) will be invoked with the index
-     * provided.  The getter can be 0 to make the property unreadable, and
-     * the setter can be 0 to make the property unmodifiable.
-     *
-     * @param name The property name to tie (full path).
-     * @param obj The object whose methods should be invoked.
-     * @param index The integer argument to pass to the getter and
-     *        setter methods.
-     * @param getter The getter method, or 0 if the value is unreadable.
-     * @param setter The setter method, or 0 if the value is unmodifiable.
-     * @param useDefault true if the setter should be invoked with any existing
-     *        property value should be; false if the old value should be
-     *        discarded; defaults to true.
-     */
-    template <class T, class V> inline void
-    Tie (const string &name, T * obj, int index,
-           V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
-                                              bool useDefault = true)
-    {
-      if (!tie(name.c_str(),
-          SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
-      {
-        cout <<
-         "Failed to tie property " << name << " to indexed object methods" << endl;
-      }
-   }
-};
-}
-#endif // FGPROPERTYMANAGER_H
-
diff --git a/src/FDM/JSBSim/FGPropulsion.cpp b/src/FDM/JSBSim/FGPropulsion.cpp
deleted file mode 100644 (file)
index 19d7e9a..0000000
+++ /dev/null
@@ -1,625 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGPropulsion.cpp
- Author:       Jon S. Berndt
- Date started: 08/20/00
- Purpose:      Encapsulates the set of engines and tanks associated
-               with this aircraft
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-The Propulsion class is the container for the entire propulsion system, which is
-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) At least one tank object is created, and is linked to an engine.
-
-At Run time each engines Calculate() method is called.
-
-HISTORY
---------------------------------------------------------------------------------
-08/20/00   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGPropulsion.h"
-#include "FGRocket.h"
-#include "FGTurbine.h"
-#include "FGPiston.h"
-#include "FGElectric.h"
-#include "FGPropertyManager.h"
-#include <sstream>
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_PROPULSION;
-
-extern short debug_lvl;
-
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
-{
-  Name = "FGPropulsion";
-
-  numSelectedFuelTanks = numSelectedOxiTanks = 0;
-  numTanks = numEngines = 0;
-  numOxiTanks = numFuelTanks = 0;
-  ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
-  tankJ.InitMatrix();
-  refuel = false;
-  fuel_freeze = false;
-
-  bind();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPropulsion::~FGPropulsion()
-{
-  for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
-  Engines.clear();
-  unbind();
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropulsion::Run(void)
-{
-  unsigned int i;
-
-  if (FGModel::Run()) return true;
-
-  double dt = State->Getdt();
-
-  vForces.InitMatrix();
-  vMoments.InitMatrix();
-
-  for (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 (i=0; i<numTanks; i++) {
-    Tanks[i]->Calculate( dt * rate );
-  }
-
-  if (refuel) DoRefuel( dt * rate );
-  
-  return false;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropulsion::GetSteadyState(void)
-{
-  double currentThrust = 0, lastThrust=-1;
-  int steady_count,j=0;
-  bool steady=false;
-
-  vForces.InitMatrix();
-  vMoments.InitMatrix();
-
-  if (!FGModel::Run()) {
-    for (unsigned int i=0; i<numEngines; i++) {
-      Engines[i]->SetTrimMode(true);
-      steady=false;
-      steady_count=0;
-      while (!steady && j < 6000) {
-        Engines[i]->Calculate();
-        lastThrust = currentThrust;
-        currentThrust = Engines[i]->GetThrust();
-        if (fabs(lastThrust-currentThrust) < 0.0001) {
-          steady_count++;
-          if (steady_count > 120) { steady=true; }
-        } else {
-          steady_count=0;
-        }
-        j++;
-      }
-      vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
-      vMoments += Engines[i]->GetMoments();     // sum body frame moments
-      Engines[i]->SetTrimMode(false);
-    }
-
-    return false;
-  } else {
-    return true;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropulsion::ICEngineStart(void)
-{
-  int j;
-
-  vForces.InitMatrix();
-  vMoments.InitMatrix();
-
-  for (unsigned int i=0; i<numEngines; i++) {
-    Engines[i]->SetTrimMode(true);
-    j=0;
-    while (!Engines[i]->GetRunning() && j < 2000) {
-      Engines[i]->Calculate();
-      j++;
-    }
-    vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
-    vMoments += Engines[i]->GetMoments();     // sum body frame moments
-    Engines[i]->SetTrimMode(false);
-  }
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGPropulsion::Load(FGConfigFile* AC_cfg)
-{
-  string token, fullpath, localpath;
-  string engineFileName, engType;
-  string parameter;
-  string enginePath = FDMExec->GetEnginePath();
-  string aircraftPath = FDMExec->GetAircraftPath();
-  double xLoc, yLoc, zLoc, Pitch, Yaw;
-  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();
-
-  while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
-
-    if (token == "AC_ENGINE") {                   // ============ READING ENGINES
-
-      engineFileName = AC_cfg->GetValue("FILE");
-
-      // 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 (Cfg_ptr) {
-        Cfg_ptr->GetNextConfigLine();
-        engType = Cfg_ptr->GetValue();
-
-        FCS->AddThrottle();
-        ThrottleAdded = true;
-
-        if (engType == "FG_ROCKET") {
-          Engines.push_back(new FGRocket(FDMExec, Cfg_ptr, numEngines));
-        } else if (engType == "FG_PISTON") {
-          Engines.push_back(new FGPiston(FDMExec, Cfg_ptr, numEngines));
-        } else if (engType == "FG_TURBINE") {
-          Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr, numEngines));
-        } else if (engType == "FG_SIMTURBINE") {
-          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, numEngines));
-        } else if (engType == "FG_ELECTRIC") {
-          Engines.push_back(new FGElectric(FDMExec, Cfg_ptr, numEngines));
-        } else {
-          cerr << fgred << "    Unrecognized engine type: " << underon << engType
-                    << underoff << " found in config file." << fgdef << endl;
-          return false;
-        }
-
-        Engines.back()->SetEngineFileName(engineFileName);
-
-        AC_cfg->GetNextConfigLine();
-        while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
-          *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.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);
-            if (debug_lvl > 0) cout << "      Feed tank: " << Feed << endl;
-          } else cerr << "Unknown identifier: " << token << " in engine file: "
-                                                        << engineFileName << endl;
-        }
-
-        if (debug_lvl > 0)  {
-          cout << "      X = " << xLoc << endl;
-          cout << "      Y = " << yLoc << endl;
-          cout << "      Z = " << zLoc << endl;
-          cout << "      Pitch = " << Pitch << endl;
-          cout << "      Yaw = " << Yaw << endl;
-        }
-
-        Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
-        numEngines++;
-
-      } else {
-
-        cerr << fgred << "\n  Could not read engine config file: " << underon <<
-                    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, FDMExec));
-      switch(Tanks[numTanks]->GetType()) {
-      case FGTank::ttFUEL:
-        numSelectedFuelTanks++;
-        numFuelTanks++;
-        break;
-      case FGTank::ttOXIDIZER:
-        numSelectedOxiTanks++;
-        numOxiTanks++;
-        break;
-      }
-
-      numTanks++;
-    }
-    AC_cfg->GetNextConfigLine();
-  }
-
-  CalculateTankInertias();
-  if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropulsion::GetPropulsionStrings(string delimeter)
-{
-  unsigned int i;
-
-  string PropulsionStrings = "";
-  bool firstime = true;
-  stringstream buf;
-
-  for (i=0; i<Engines.size(); i++) {
-    if (firstime)  firstime = false;
-    else           PropulsionStrings += delimeter;
-
-    PropulsionStrings += Engines[i]->GetEngineLabels(delimeter);
-  }
-  for (i=0; i<Tanks.size(); i++) {
-    if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i;
-    else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i;
-  }
-
-  return PropulsionStrings;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGPropulsion::GetPropulsionValues(string delimeter)
-{
-  unsigned int i;
-
-  string PropulsionValues = "";
-  bool firstime = true;
-  stringstream buf;
-
-  for (i=0; i<Engines.size(); i++) {
-    if (firstime)  firstime = false;
-    else           PropulsionValues += delimeter;
-
-    PropulsionValues += Engines[i]->GetEngineValues(delimeter);
-  }
-  for (i=0; i<Tanks.size(); i++) {
-    buf << delimeter;
-    buf << Tanks[i]->GetContents();
-  }
-
-  return PropulsionValues;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGColumnVector3& FGPropulsion::GetTanksMoment(void)
-{
-  iTank = Tanks.begin();
-  vXYZtank_arm.InitMatrix();
-  while (iTank < Tanks.end()) {
-    vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents();
-    vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents();
-    vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents();
-    iTank++;
-  }
-  return vXYZtank_arm;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGPropulsion::GetTanksWeight(void)
-{
-  double Tw = 0.0;
-
-  iTank = Tanks.begin();
-  while (iTank < Tanks.end()) {
-    Tw += (*iTank)->GetContents();
-    iTank++;
-  }
-  return Tw;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGMatrix33& FGPropulsion::CalculateTankInertias(void)
-{
-  unsigned int size;
-
-  size = Tanks.size();
-  if (size == 0) return tankJ;
-
-  tankJ = FGMatrix33();
-
-  for (unsigned int i=0; i<size; i++)
-    tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
-                                               Tanks[i]->GetXYZ() );
-
-  return tankJ;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropulsion::SetMagnetos(int setting)
-{
-  if (ActiveEngine < 0) {
-    for (unsigned i=0; i<Engines.size(); i++) {
-      ((FGPiston*)Engines[i])->SetMagnetos(setting);
-    }
-  } else {
-    ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropulsion::SetStarter(int setting)
-{
-  if (ActiveEngine < 0) {
-    for (unsigned i=0; i<Engines.size(); i++) {
-      if (setting == 0)
-        Engines[i]->SetStarter(false);
-      else
-        Engines[i]->SetStarter(true);
-    }
-  } else {
-    if (setting == 0)
-      Engines[ActiveEngine]->SetStarter(false);
-    else
-      Engines[ActiveEngine]->SetStarter(true);
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropulsion::SetCutoff(int setting)
-{
-  if (ActiveEngine < 0) {
-    for (unsigned i=0; i<Engines.size(); i++) {
-      if (setting == 0)
-        ((FGTurbine*)Engines[i])->SetCutoff(false);
-      else
-        ((FGTurbine*)Engines[i])->SetCutoff(true);
-    }
-  } else {
-    if (setting == 0)
-      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
-    else
-      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropulsion::SetActiveEngine(int engine)
-{
-  if (engine >= Engines.size() || engine < 0)
-    ActiveEngine = -1;
-  else
-    ActiveEngine = 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::SetFuelFreeze(bool f) 
-{
-  fuel_freeze = f;
-  for (unsigned int i=0; i<numEngines; i++) {
-    Engines[i]->SetFuelFreeze(f);
-  }
-}  
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropulsion::bind(void)
-{
-  typedef double (FGPropulsion::*PMF)(int) const;
-  typedef int (FGPropulsion::*iPMF)(void) const;
-
-  PropertyManager->Tie("propulsion/magneto_cmd", this,
-                       (iPMF)0, &FGPropulsion::SetMagnetos, true);
-  PropertyManager->Tie("propulsion/starter_cmd", this,
-                       (iPMF)0, &FGPropulsion::SetStarter,  true);
-  PropertyManager->Tie("propulsion/cutoff_cmd", this,
-                       (iPMF)0, &FGPropulsion::SetCutoff,   true);
-
-  PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
-                       (PMF)&FGPropulsion::GetForces);
-  PropertyManager->Tie("forces/fby-prop-lbs", this,2,
-                       (PMF)&FGPropulsion::GetForces);
-  PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
-                       (PMF)&FGPropulsion::GetForces);
-  PropertyManager->Tie("moments/l-prop-lbsft", this,1,
-                       (PMF)&FGPropulsion::GetMoments);
-  PropertyManager->Tie("moments/m-prop-lbsft", this,2,
-                       (PMF)&FGPropulsion::GetMoments);
-  PropertyManager->Tie("moments/n-prop-lbsft", this,3,
-                       (PMF)&FGPropulsion::GetMoments);
-
-  PropertyManager->Tie("propulsion/active_engine", this,
-           (iPMF)&FGPropulsion::GetActiveEngine, &FGPropulsion::SetActiveEngine, true);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropulsion::unbind(void)
-{
-  PropertyManager->Untie("propulsion/magneto_cmd");
-  PropertyManager->Untie("propulsion/starter_cmd");
-  PropertyManager->Untie("propulsion/cutoff_cmd");
-  PropertyManager->Untie("propulsion/active_engine");
-  PropertyManager->Untie("forces/fbx-prop-lbs");
-  PropertyManager->Untie("forces/fby-prop-lbs");
-  PropertyManager->Untie("forces/fbz-prop-lbs");
-  PropertyManager->Untie("moments/l-prop-lbsft");
-  PropertyManager->Untie("moments/m-prop-lbsft");
-  PropertyManager->Untie("moments/n-prop-lbsft");
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGPropulsion::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: FGPropulsion" << endl;
-    if (from == 1) cout << "Destroyed:    FGPropulsion" << 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/FGPropulsion.h b/src/FDM/JSBSim/FGPropulsion.h
deleted file mode 100644 (file)
index 6d143f7..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGPropulsion.h
- Author:       Jon S. Berndt
- Date started: 08/20/00
-
- ------------- 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
---------------------------------------------------------------------------------
-08/20/00   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGPROPULSION_H
-#define FGPROPULSION_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <vector>
-#    include <iterator>
-#  else
-#    include <vector.h>
-#    include <iterator.h>
-#  endif
-#else
-#  include <vector>
-#  include <iterator>
-#endif
-
-#include "FGModel.h"
-#include "FGEngine.h"
-#include "FGTank.h"
-#include "FGMatrix33.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_PROPULSION "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Propulsion management class.
-    The Propulsion class is the container for the entire propulsion system, which is
-    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
-    -# At least one tank object is created, and is linked to an engine.
-
-    At Run time each engines Calculate() method is called.
-    @author Jon S. Berndt
-    @version $Id$
-    @see
-    FGEngine
-    FGTank
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGPropulsion : public FGModel
-{
-public:
-  /// Constructor
-  FGPropulsion(FGFDMExec*);
-  /// Destructor
-  ~FGPropulsion();
-
-  /** Executes the propulsion model.
-      The initial plan for the FGPropulsion class calls for Run() to be executed,
-      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] 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.
-      @return true if successfully loaded, otherwise false */
-  bool Load(FGConfigFile* AC_cfg);
-
-  /// Retrieves the number of engines defined for the aircraft.
-  inline unsigned int GetNumEngines(void) const {return Engines.size();}
-
-  /** Retrieves an engine object pointer from the list of engines.
-      @param index the engine index within the vector container
-      @return the address of the specific engine, or zero if no such engine is
-              available */
-  inline FGEngine* GetEngine(unsigned int index) {
-                      if (index <= Engines.size()-1) return Engines[index];
-                      else                           return 0L;      }
-
-  /// Retrieves the number of tanks defined for the aircraft.
-  inline unsigned int GetNumTanks(void) const {return Tanks.size();}
-
-  /** Retrieves a tank object pointer from the list of tanks.
-      @param index the tank index within the vector container
-      @return the address of the specific tank, or zero if no such tank is
-              available */
-  inline FGTank* GetTank(unsigned int index) {
-                      if (index <= Tanks.size()-1) return Tanks[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 until thrust output steady (used for trimming) */
-  bool GetSteadyState(void);
-
-  /** starts the engines in IC mode (dt=0).  All engine-specific setup must
-      be done before calling this (i.e. magnetos, starter engage, etc.) */
-  bool ICEngineStart(void);
-
-  string GetPropulsionStrings(string delimeter);
-  string GetPropulsionValues(string delimeter);
-
-  inline FGColumnVector3& GetForces(void)  {return vForces; }
-  inline double GetForces(int n) const { return vForces(n);}
-  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);
-
-  inline int GetActiveEngine(void) const
-  {
-    return ActiveEngine;
-  }
-
-  inline int GetActiveEngine(void);
-  inline bool GetFuelFreeze(void) {return fuel_freeze;}
-
-  void SetMagnetos(int setting);
-  void SetStarter(int setting);
-  void SetCutoff(int setting=0);
-  void SetActiveEngine(int engine);
-  void SetFuelFreeze(bool f);  
-  FGMatrix33& CalculateTankInertias(void);
-
-  void bind();
-  void unbind();
-
-private:
-  vector <FGEngine*>   Engines;
-  vector <FGTank*>     Tanks;
-  vector <FGTank*>::iterator iTank;
-  unsigned int numSelectedFuelTanks;
-  unsigned int numSelectedOxiTanks;
-  unsigned int numFuelTanks;
-  unsigned int numOxiTanks;
-  unsigned int numEngines;
-  unsigned int numTanks;
-  int ActiveEngine;
-  FGColumnVector3 vForces;
-  FGColumnVector3 vMoments;
-  FGColumnVector3 vTankXYZ;
-  FGColumnVector3 vXYZtank_arm;
-  FGMatrix33 tankJ;
-  bool refuel;
-  bool fuel_freeze;
-
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGQuaternion.cpp b/src/FDM/JSBSim/FGQuaternion.cpp
deleted file mode 100644 (file)
index bc32c81..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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 HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#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 {
-  double norm = Magnitude();
-  if (norm == 0.0)
-    return FGQuaternion::zero();
-  double rnorm = 1.0/norm;
-
-  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 rnorm*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
deleted file mode 100644 (file)
index 2800a15..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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);
-
-  /** Initializer by one euler angle.
-      Initialize the quaternion with the single euler angle where its index
-      is given in the first argument.
-      @param idx Index of the euler angle to initialize
-      @param angle The euler angle in radians  */
-  FGQuaternion(int idx, double angle)
-    : mCacheValid(false) {
-    double angle2 = 0.5*angle;
-
-    double Sangle2 = sin(angle2);
-    double Cangle2 = cos(angle2);
-
-    if (idx == ePhi) {
-      Entry(1) = Cangle2;
-      Entry(2) = Sangle2;
-      Entry(3) = 0.0;
-      Entry(4) = 0.0;
-
-    } else if (idx == eTht) {
-      Entry(1) = Cangle2;
-      Entry(2) = 0.0;
-      Entry(3) = Sangle2;
-      Entry(4) = 0.0;
-
-    } else {
-      Entry(1) = Cangle2;
-      Entry(2) = 0.0;
-      Entry(3) = 0.0;
-      Entry(4) = Sangle2;
-
-    }
-  }
-
-  /// 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(void) const { ComputeDerived(); return mT; }
-
-  /** Backward transformation matrix.
-      @return a reference to the inverse transformation/rotation matrix
-      corresponding to this quaternion rotation.  */
-  const FGMatrix33& GetTInv(void) 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(void) const {
-    ComputeDerived();
-    return mEulerAngles;
-  }
-
-  /** Retrieves the Euler angles.
-      @param i the euler angle index.
-      @return a reference to the i-th euler angles corresponding
-      to this quaternion rotation.
-      @units radians */
-  double GetEuler(int i) const {
-    ComputeDerived();
-    return mEulerAngles(i);
-  }
-
-  /** Retrieves the Euler angles.
-      @param i the euler angle index.
-      @return a reference to the i-th euler angles corresponding
-      to this quaternion rotation.
-      @units degrees */
-  double GetEulerDeg(int i) const {
-    ComputeDerived();
-    return radtodeg*mEulerAngles(i);
-  }
-
-  /** Retrieves sine of the given euler angle.
-      @return the sine of the Euler angle theta (pitch attitude) corresponding
-      to this quaternion rotation.  */
-  double GetSinEuler(int i) const {
-    ComputeDerived();
-    return mEulerSines(i);
-  }
-
-  /** Retrieves cosine of the given euler angle.
-      @return the sine of the Euler angle theta (pitch attitude) corresponding
-      to this quaternion rotation.  */
-  double GetCosEuler(int i) const {
-    ComputeDerived();
-    return mEulerCosines(i);
-  }
-
-  /** 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;
-  }
-
-  /** Inverse of the quaternion.
-
-      Compute and return the inverse of the quaternion so that the orientation
-      represented with *this multiplied with the returned value is equal to
-      the identity orientation.
-  */
-  FGQuaternion Inverse(void) const {
-    double norm = Magnitude();
-    if (norm == 0.0)
-      return *this;
-    double rNorm = 1.0/norm;
-    return FGQuaternion( Entry(1)*rNorm, -Entry(2)*rNorm,
-                         -Entry(3)*rNorm, -Entry(4)*rNorm );
-  }
-
-  /** Conjugate of the quaternion.
-
-      Compute and return the conjugate of the quaternion. This one is equal
-      to the inverse iff the quaternion is normalized.
-  */
-  FGQuaternion Conjugate(void) const {
-    return FGQuaternion( Entry(1), -Entry(2), -Entry(3), -Entry(4) );
-  }
-
-  friend FGQuaternion operator*(double, const FGQuaternion&);
-
-  /** Length of the vector.
-
-      Compute and return the euclidean norm of this vector.
-  */
-  double Magnitude(void) 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(void) 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(void);
-
-  /** 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 the real worker routine
-      \ref FGQuaternion::ComputeDerivedUnconditional(void) const
-      is called.
-      This function is inlined to avoid function calls in the fast path. */
-  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
diff --git a/src/FDM/JSBSim/FGRocket.cpp b/src/FDM/JSBSim/FGRocket.cpp
deleted file mode 100644 (file)
index e278cca..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGRocket.cpp
- Author:       Jon S. Berndt
- Date started: 09/12/2000
- Purpose:      This module models a rocket engine
-
- ------------- Copyright (C) 2000  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 descends from the FGEngine class and models a rocket engine based on
-parameters given in the engine config file for this class
-
-HISTORY
---------------------------------------------------------------------------------
-09/12/2000  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <sstream>
-
-#include "FGRocket.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_ROCKET;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGRocket::FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number)
-  : FGEngine(exec, engine_number)
-{
-  string token;
-
-  Name = Eng_cfg->GetValue("NAME");
-  Eng_cfg->GetNextConfigLine();
-
-  while (Eng_cfg->GetValue() != string("/FG_ROCKET")) {
-    *Eng_cfg >> token;
-    if      (token == "SHR")           *Eng_cfg >> SHR;
-    else if (token == "MAX_PC")        *Eng_cfg >> maxPC;
-    else if (token == "PROP_EFF")      *Eng_cfg >> propEff;
-    else if (token == "MAXTHROTTLE")   *Eng_cfg >> MaxThrottle;
-    else if (token == "MINTHROTTLE")   *Eng_cfg >> MinThrottle;
-    else if (token == "SLFUELFLOWMAX") *Eng_cfg >> SLFuelFlowMax;
-    else if (token == "SLOXIFLOWMAX")  *Eng_cfg >> SLOxiFlowMax;
-    else if (token == "VARIANCE")      *Eng_cfg >> Variance;
-    else cerr << "Unhandled token in Engine config file: " << token << endl;
-  }
-
-  Debug(0);
-
-  Type = etRocket;
-  Flameout = false;
-
-  PC = 0.0;
-  kFactor = (2.0*SHR*SHR/(SHR-1.0))*pow(2.0/(SHR+1), (SHR+1)/(SHR-1));
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGRocket::~FGRocket(void)
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGRocket::Calculate(void)
-{
-  double Cf=0;
-
-  if (!Flameout && !Starved) ConsumeFuel();
-
-  Throttle = FCS->GetThrottlePos(EngineNumber);
-
-  if (Throttle < MinThrottle || Starved) {
-    PctPower = Thrust = 0.0; // desired thrust
-    Flameout = true;
-    PC = 0.0;
-  } else {
-    PctPower = Throttle / MaxThrottle;
-    PC = maxPC*PctPower * (1.0 + Variance * ((double)rand()/(double)RAND_MAX - 0.5));
-    // The Cf (below) is CF from Eqn. 3-30, "Rocket Propulsion Elements", Fifth Edition,
-    // George P. Sutton. Note that the thruster function GetPowerRequired() might
-    // be better called GetResistance() or something; this function returns the
-    // nozzle exit pressure.
-    Cf = sqrt(kFactor*(1 - pow(Thruster->GetPowerRequired()/(PC), (SHR-1)/SHR)));
-    Flameout = false;
-  }
-
-  return Thrust = Thruster->Calculate(Cf*maxPC*PctPower*propEff);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGRocket::GetEngineLabels(string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << Name << "_ChamberPress[" << EngineNumber << "]" << delimeter
-      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGRocket::GetEngineValues(string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << PC << delimeter << Thruster->GetThrusterValues(EngineNumber, delimeter);
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGRocket::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "      Engine Name: " << Name << endl;
-      cout << "      Specific Heat Ratio = " << SHR << endl;
-      cout << "      Maximum Chamber Pressure = " << maxPC << endl;
-      cout << "      Propulsive Efficiency = " << propEff << endl;
-      cout << "      MaxThrottle = " << MaxThrottle << endl;
-      cout << "      MinThrottle = " << MinThrottle << endl;
-      cout << "      FuelFlowMax = " << SLFuelFlowMax << endl;
-      cout << "      OxiFlowMax = " << SLOxiFlowMax << endl;
-      cout << "      Variance = " << Variance << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGRocket" << endl;
-    if (from == 1) cout << "Destroyed:    FGRocket" << 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/FGRocket.h b/src/FDM/JSBSim/FGRocket.h
deleted file mode 100644 (file)
index 00befb0..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGRocket.h
- Author:       Jon S. Berndt
- Date started: 09/12/2000
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-09/12/2000  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGROCKET_H
-#define FGROCKET_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGEngine.h"
-#include "FGConfigFile.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_ROCKET "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models a generic rocket engine.
-    The rocket engine is modeled given the following parameters:
-    <ul>
-        <li>Chamber pressure (in psf)</li>
-        <li>Specific heat ratio (usually about 1.2 for hydrocarbon fuel and LOX)</li>
-        <li>Propulsive efficiency (in percent, from 0 to 1.0)</li>
-        <li>Variance (in percent, from 0 to 1.0, nominally 0.05)</li>
-    </ul>
-    Additionally, the following control inputs, operating characteristics, and
-    location are required, as with all other engine types:
-    <ul>
-        <li>Throttle setting (in percent, from 0 to 1.0)</li>
-        <li>Maximum allowable throttle setting</li>
-        <li>Minimum working throttle setting</li>
-        <li>Sea level fuel flow at maximum thrust</li>
-        <li>Sea level oxidizer flow at maximum thrust</li>
-        <li>X, Y, Z location in structural coordinate frame</li>
-        <li>Pitch and Yaw</li>
-    </ul>
-    The nozzle exit pressure (p2) is returned via a
-    call to FGNozzle::GetPowerRequired(). This exit pressure is used,
-    along with chamber pressure and specific heat ratio, to get the
-    thrust coefficient for the throttle setting. This thrust
-    coefficient is multiplied by the chamber pressure and then passed
-    to the nozzle Calculate() routine, where the thrust force is
-    determined.
-
-    @author Jon S. Berndt
-    $Id$
-    @see FGNozzle,
-    FGThruster,
-    FGForce,
-    FGEngine,
-    FGPropulsion,
-    FGTank
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGRocket : public FGEngine
-{
-public:
-  /** Constructor.
-      @param exec pointer to JSBSim parent object, the FDM Executive.
-      @param Eng_cfg pointer to the config file object.
-      @param engine_number engine number */
-  FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number);
-
-  /** Destructor */
-  ~FGRocket(void);
-
-  /** Determines the thrust coefficient.
-      @return thrust coefficient times chamber pressure */
-  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
-      sustainable setting.
-      @return true if engine has flamed out. */
-  bool GetFlameout(void) {return Flameout;}
-  string GetEngineLabels(string delimeter);
-  string GetEngineValues(string delimeter);
-
-private:
-  double SHR;
-  double maxPC;
-  double propEff;
-  double kFactor;
-  double Variance;
-  double PC;
-  bool Flameout;
-
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGRotor.cpp b/src/FDM/JSBSim/FGRotor.cpp
deleted file mode 100644 (file)
index 58fee45..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGRotor.cpp
- Author:       Jon S. Berndt
- Date started: 08/24/00
- Purpose:      Encapsulates the rotor object
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/24/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGRotor.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_ROTOR;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGRotor::FGRotor(FGFDMExec *FDMExec) : FGThruster(FDMExec)
-{
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGRotor::~FGRotor()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGRotor::Calculate(double PowerAvailable)
-{
-  return 0.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGRotor::GetThrusterLabels(int id, string delimeter)
-{
-  return "";
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGRotor::GetThrusterValues(int id, string delimeter)
-{
-  return "";
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGRotor::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: FGRotor" << endl;
-    if (from == 1) cout << "Destroyed:    FGRotor" << 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/FGRotor.h b/src/FDM/JSBSim/FGRotor.h
deleted file mode 100644 (file)
index 2e4b3b3..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGRotor.h
- Author:       Jon S. Berndt
- Date started: 08/24/00
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/24/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGROTOR_H
-#define FGROTOR_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGThruster.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_ROTOR "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models a rotor (such as for a helicopter); NOT YET IMPLEMENTED.
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGRotor : public FGThruster {
-
-public:
-  FGRotor(FGFDMExec *FDMExec);
-  ~FGRotor();
-
-  double Calculate(double);
-  string GetThrusterLabels(int id, string delimeter);
-  string GetThrusterValues(int id, string delimeter);
-
-private:
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
diff --git a/src/FDM/JSBSim/FGScript.cpp b/src/FDM/JSBSim/FGScript.cpp
deleted file mode 100644 (file)
index 4fe946d..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGScript.cpp
- Author:       Jon S. Berndt
- Date started: 12/21/01
- Purpose:      Loads and runs JSBSim scripts.
-
- ------------- 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 wraps up the simulation scripting routines.
-
-HISTORY
---------------------------------------------------------------------------------
-12/21/01   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  include STL_IOSTREAM
-#  include STL_ITERATOR
-#else
-#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
-#    include <iostream.h>
-#  else
-#    include <iostream>
-#  endif
-#  include <iterator>
-#endif
-
-#include "FGScript.h"
-#include "FGConfigFile.h"
-#include "FGTrim.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_FGSCRIPT;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-GLOBAL DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-// Constructor
-
-FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
-{
-  State = FDMExec->GetState();
-  PropertyManager=FDMExec->GetPropertyManager();
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGScript::~FGScript()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGScript::LoadScript( string script )
-{
-  FGConfigFile Script(script);
-  string token="";
-  string aircraft="";
-  string initialize="";
-  string prop_name;
-  bool result = false;
-  double dt = 0.0;
-  struct condition *newCondition;
-
-  if (!Script.IsOpen()) return false;
-
-  Script.GetNextConfigLine();
-  if (Script.GetValue("runscript").length() <= 0) {
-    cerr << "File: " << script << " is not a script file" << endl;
-    delete FDMExec;
-    return false;
-  }
-  ScriptName = Script.GetValue("name");
-  Scripted = true;
-
-  if (debug_lvl > 0) cout << "Reading and running from script file " << ScriptName << endl << endl;
-
-  while (Script.GetNextConfigLine() != string("EOF") && Script.GetValue() != string("/runscript")) {
-    token = Script.GetValue();
-    if (token == "use") {
-      if ((token = Script.GetValue("aircraft")) != string("")) {
-        aircraft = token;
-        result = FDMExec->LoadModel(aircraft);
-        if (!result) {
-          cerr << "Aircraft file " << aircraft << " was not found" << endl;
-          exit(-1);
-        }
-        if (debug_lvl > 0) cout << "  Use aircraft: " << token << endl;
-      } else if ((token = Script.GetValue("initialize")) != string("")) {
-        initialize = token;
-        if (debug_lvl > 0) cout << "  Use reset file: " << token << endl;
-      } else {
-        cerr << "Unknown 'use' keyword: \"" << token << "\"" << endl;
-      }
-    } else if (token == "run") {
-      StartTime = strtod(Script.GetValue("start").c_str(), NULL);
-      State->Setsim_time(StartTime);
-      EndTime   = strtod(Script.GetValue("end").c_str(), NULL);
-      dt        = strtod(Script.GetValue("dt").c_str(), NULL);
-      State->Setdt(dt);
-      Script.GetNextConfigLine();
-      token = Script.GetValue();
-      while (token != string("/run")) {
-
-        if (token == "when") {
-          Script.GetNextConfigLine();
-          token = Script.GetValue();
-          newCondition = new struct condition();
-          while (token != string("/when")) {
-            if (token == "parameter") {
-              prop_name = Script.GetValue("name");
-              newCondition->TestParam.push_back( PropertyManager->GetNode(prop_name) );
-              newCondition->TestValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
-              newCondition->Comparison.push_back(Script.GetValue("comparison"));
-            } else if (token == "set") {
-              prop_name = Script.GetValue("name");
-              newCondition->SetParam.push_back( PropertyManager->GetNode(prop_name) );
-              newCondition->SetValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
-              newCondition->Triggered.push_back(false);
-              newCondition->OriginalValue.push_back(0.0);
-              newCondition->newValue.push_back(0.0);
-              newCondition->StartTime.push_back(0.0);
-              newCondition->EndTime.push_back(0.0);
-              string tempCompare = Script.GetValue("type");
-              if      (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);
-              else if (tempCompare == "FG_BOOL")  newCondition->Type.push_back(FG_BOOL);
-              else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);
-              else                                newCondition->Type.push_back((eType)0);
-              tempCompare = Script.GetValue("action");
-              if      (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);
-              else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);
-              else if (tempCompare == "FG_EXP")  newCondition->Action.push_back(FG_EXP);
-              else                               newCondition->Action.push_back((eAction)0);
-
-              if (Script.GetValue("persistent") == "true")
-                newCondition->Persistent.push_back(true);
-              else
-                newCondition->Persistent.push_back(false);
-
-              newCondition->TC.push_back(strtod(Script.GetValue("tc").c_str(), NULL));
-
-            } else {
-              cerr << "Unrecognized keyword in script file: \" [when] " << token << "\"" << endl;
-            }
-            Script.GetNextConfigLine();
-            token = Script.GetValue();
-          }
-          Conditions.push_back(*newCondition);
-          Script.GetNextConfigLine();
-          token = Script.GetValue();
-
-        } else {
-          cerr << "Error reading script file: expected \"when\", got \"" << token << "\"" << endl;
-        }
-
-      }
-    } else if (token.empty()) {
-     // do nothing
-    } else {
-      cerr << "Unrecognized keyword in script file: \"" << token << "\" [runscript] " << endl;
-    }
-  }
-
-  if (aircraft == "") {
-    cerr << "Aircraft file not loaded in script" << endl;
-    exit(-1);
-  }
-
-  Debug(4);
-
-
-  FGInitialCondition *IC=FDMExec->GetIC();
-  if ( ! IC->Load( initialize )) {
-    cerr << "Initialization unsuccessful" << endl;
-    exit(-1);
-  }
-/* comment this out for conversion capability
-  FGTrim fgt(FDMExec, tFull);
-  if ( !fgt.DoTrim() ) {
-    cout << "Trim Failed" << endl;
-  }
-  fgt.Report();
-*/
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGScript::RunScript(void)
-{
-  vector <struct condition>::iterator iC = Conditions.begin();
-  bool truth = false;
-  bool WholeTruth = false;
-  unsigned i;
-
-  double currentTime = State->Getsim_time();
-  double newSetValue = 0;
-
-  if (currentTime > EndTime) return false;
-
-  while (iC < Conditions.end()) {
-    // determine whether the set of conditional tests for this condition equate
-    // to true
-    for (i=0; i<iC->TestValue.size(); i++) {
-           if (iC->Comparison[i] == "lt")
-              truth = iC->TestParam[i]->getDoubleValue() <  iC->TestValue[i];
-      else if (iC->Comparison[i] == "le")
-              truth = iC->TestParam[i]->getDoubleValue() <= iC->TestValue[i];
-      else if (iC->Comparison[i] == "eq")
-              truth = iC->TestParam[i]->getDoubleValue() == iC->TestValue[i];
-      else if (iC->Comparison[i] == "ge")
-              truth = iC->TestParam[i]->getDoubleValue() >= iC->TestValue[i];
-      else if (iC->Comparison[i] == "gt")
-              truth = iC->TestParam[i]->getDoubleValue() >  iC->TestValue[i];
-      else if (iC->Comparison[i] == "ne")
-              truth = iC->TestParam[i]->getDoubleValue() != iC->TestValue[i];
-      else
-              cerr << "Bad comparison" << endl;
-
-      if (i == 0) WholeTruth = truth;
-      else        WholeTruth = WholeTruth && truth;
-
-      if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false;
-    }
-
-    // if the conditions are true, do the setting of the desired parameters
-
-    if (WholeTruth) {
-      for (i=0; i<iC->SetValue.size(); i++) {
-        if ( ! iC->Triggered[i]) {
-          iC->OriginalValue[i] = iC->SetParam[i]->getDoubleValue();
-          switch (iC->Type[i]) {
-          case FG_VALUE:
-            iC->newValue[i] = iC->SetValue[i];
-            break;
-          case FG_DELTA:
-            iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i];
-            break;
-          case FG_BOOL:
-            iC->newValue[i] = iC->SetValue[i];
-            break;
-          default:
-            cerr << "Invalid Type specified" << endl;
-            break;
-          }
-          iC->Triggered[i] = true;
-          iC->StartTime[i] = currentTime;
-        }
-
-        switch (iC->Action[i]) {
-        case FG_RAMP:
-        newSetValue = (currentTime - iC->StartTime[i])/(iC->TC[i])
-                      * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
-          if (newSetValue > iC->newValue[i]) newSetValue = iC->newValue[i];
-          break;
-        case FG_STEP:
-          newSetValue = iC->newValue[i];
-          break;
-        case FG_EXP:
-          newSetValue = (1 - exp(-(currentTime - iC->StartTime[i])/(iC->TC[i])))
-              * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
-          break;
-        default:
-          cerr << "Invalid Action specified" << endl;
-          break;
-        }
-        iC->SetParam[i]->setDoubleValue(newSetValue);
-      }
-    }
-    iC++;
-  }
-  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 FGScript::Debug(int from)
-{
-  unsigned int i;
-
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-    } else if (from == 3) {
-    } else if (from == 4)  { // print out script data
-      vector <struct condition>::iterator iterConditions = Conditions.begin();
-      int count=0;
-
-      cout << "\n  Script goes from " << StartTime << " to " << EndTime
-           << " with dt = " << State->Getdt() << endl << endl;
-
-      while (iterConditions < Conditions.end()) {
-        cout << "  Condition: " << count++ << endl;
-        cout << "    if (";
-
-        for (i=0; i<iterConditions->TestValue.size(); i++) {
-          if (i>0) cout << " and" << endl << "        ";
-          cout << "(" << iterConditions->TestParam[i]->GetName()
-                      << " " << iterConditions->Comparison[i] << " "
-                      << iterConditions->TestValue[i] << ")";
-        }
-        cout << ") then {";
-
-        for (i=0; i<iterConditions->SetValue.size(); i++) {
-          cout << endl << "      set " << iterConditions->SetParam[i]->GetName()
-               << " to " << iterConditions->SetValue[i];
-
-          switch (iterConditions->Type[i]) {
-          case FG_VALUE:
-            cout << " (constant";
-            break;
-          case FG_DELTA:
-            cout << " (delta";
-            break;
-          case FG_BOOL:
-            cout << " (boolean";
-            break;
-          default:
-            cout << " (unspecified type";
-          }
-
-          switch (iterConditions->Action[i]) {
-          case FG_RAMP:
-            cout << " via ramp";
-            break;
-          case FG_STEP:
-            cout << " via step";
-            break;
-          case FG_EXP:
-            cout << " via exponential approach";
-            break;
-          default:
-            cout << " via unspecified action";
-          }
-
-          if (!iterConditions->Persistent[i]) cout << endl
-                             << "                              once";
-          else cout << endl
-                             << "                              repeatedly";
-
-          if (iterConditions->Action[i] == FG_RAMP ||
-              iterConditions->Action[i] == FG_EXP) cout << endl
-                             << "                              with time constant "
-                             << iterConditions->TC[i];
-        }
-        cout << ")" << endl << "    }" << endl << endl;
-
-        iterConditions++;
-      }
-
-      cout << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGScript" << endl;
-    if (from == 1) cout << "Destroyed:    FGScript" << 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/FGScript.h b/src/FDM/JSBSim/FGScript.h
deleted file mode 100644 (file)
index 7b4587a..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Header:       FGScript.h
- Author:       Jon Berndt
- Date started: 12/21/2001
-
- ------------- Copyright (C) 2001  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/21/01   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGSCRIPT_HEADER_H
-#define FGSCRIPT_HEADER_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGJSBBase.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
-#include <vector>
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_FGSCRIPT "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates the JSBSim scripting capability.
-    <h4>Scripting support provided via FGScript.</h4>
-
-    <p>There is simple scripting support provided in the FGScript
-    class. Commands are specified using the <em>Simple Scripting
-    Directives for JSBSim</em> (SSDJ). The script file is in XML
-    format. A test condition (or conditions) can be set up in the
-    script and when the condition evaluates to true, the specified
-    action[s] is/are taken. A test condition can be <em>persistent</em>,
-    meaning that if a test condition evaluates to true, then passes
-    and evaluates to false, the condition is reset and may again be
-    triggered. When the set of tests evaluates to true for a given
-    condition, an item may be set to another value. This value might
-    be a boolean, a value, or a delta value, and the change from the
-    current value to the new value can be either via a step function,
-    a ramp, or an exponential approach. The speed of a ramp or
-    approach is specified via the time constant. Here is the format
-    of the script file:</p>
-
-    <pre><strong>&lt;?xml version=&quot;1.0&quot;?&gt;
-    &lt;runscript name=&quot;C172-01A&quot;&gt;
-
-    &lt;!--
-    This run is for testing C172 runs
-    --&gt;
-
-    &lt;use aircraft=&quot;c172&quot;&gt;
-    &lt;use initialize=&quot;reset00&quot;&gt;
-
-    &lt;run start=&quot;0.0&quot; end=&quot;4.5&quot; dt=&quot;0.05&quot;&gt;
-      &lt;when&gt;
-        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;0.25&quot;&gt;
-        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;0.50&quot;&gt;
-        &lt;set name=&quot;FG_AILERON_CMD&quot; type=&quot;FG_VALUE&quot; value=&quot;0.25&quot;
-        action=&quot;FG_STEP&quot; persistent=&quot;false&quot; tc =&quot;0.25&quot;&gt;
-      &lt;/when&gt;
-      &lt;when&gt;
-        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;0.5&quot;&gt;
-        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;1.5&quot;&gt;
-        &lt;set name=&quot;FG_AILERON_CMD&quot; type=&quot;FG_DELTA&quot; value=&quot;0.5&quot;
-        action=&quot;FG_EXP&quot; persistent=&quot;false&quot; tc =&quot;0.5&quot;&gt;
-      &lt;/when&gt;
-      &lt;when&gt;
-        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;1.5&quot;&gt;
-        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;2.5&quot;&gt;
-        &lt;set name=&quot;FG_RUDDER_CMD&quot; type=&quot;FG_DELTA&quot; value=&quot;0.5&quot;
-        action=&quot;FG_RAMP&quot; persistent=&quot;false&quot; tc =&quot;0.5&quot;&gt;
-      &lt;/when&gt;
-    &lt;/run&gt;
-
-    &lt;/runscript&gt;</strong></pre>
-
-    <p>The first line must always be present. The second line
-    identifies this file as a script file, and gives a descriptive
-    name to the script file. Comments are next, delineated by the
-    &lt;!-- and --&gt; symbols. The aircraft and initialization files
-    to be used are specified in the &quot;use&quot; lines. Next,
-    comes the &quot;run&quot; section, where the conditions are
-    described in &quot;when&quot; clauses.</p>
-    @author Jon S. Berndt
-    @version "$Id$"
-
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGScript : public FGJSBBase
-{
-public:
-  /// Default constructor
-  FGScript(FGFDMExec* exec);
-
-  /// Default destructor
-  ~FGScript();
-
-  /** Loads a script to drive JSBSim (usually in standalone mode).
-      The language is the Simple Script Directives for JSBSim (SSDJ).
-      @param script the filename (including path name, if any) for the script.
-      @return true if successful */
-  bool LoadScript( string script );
-
-  /** This function is called each pass through the executive Run() method IF
-      scripting is enabled. 
-      @return false if script should exit (i.e. if time limits are violated */
-  bool RunScript(void);
-
-private:
-  enum eAction {
-    FG_RAMP  = 1,
-    FG_STEP  = 2,
-    FG_EXP   = 3
-  };
-
-  enum eType {
-    FG_VALUE = 1,
-    FG_DELTA = 2,
-    FG_BOOL  = 3
-  };
-
-  struct condition {
-    vector <FGPropertyManager*>  TestParam;
-    vector <FGPropertyManager*>  SetParam;
-    vector <double>  TestValue;
-    vector <double>  SetValue;
-    vector <string>  Comparison;
-    vector <double>  TC;
-    vector <bool>    Persistent;
-    vector <eAction> Action;
-    vector <eType>   Type;
-    vector <bool>    Triggered;
-    vector <double>  newValue;
-    vector <double>  OriginalValue;
-    vector <double>  StartTime;
-    vector <double>  EndTime;
-
-    condition() {
-    }
-  };
-
-  bool Scripted;
-
-  string  ScriptName;
-  double  StartTime;
-  double  EndTime;
-  vector <struct condition> Conditions;
-
-  FGFDMExec* FDMExec;
-  FGState* State;
-  FGPropertyManager* PropertyManager;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
index 1f581b96af525b8190194cbcb1abb9cad3e4b7fb..cee30b905308bee81bea04dc1c8b38f2a6e56c4e 100644 (file)
@@ -36,10 +36,6 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
 #ifdef FGFS
 #  include <simgear/compiler.h>
 #  include <math.h>
@@ -81,7 +77,6 @@ FGState::FGState(FGFDMExec* fdex)
   Propagate    = FDMExec->GetPropagate();
   Auxiliary    = FDMExec->GetAuxiliary();
   FCS          = FDMExec->GetFCS();
-  Output       = FDMExec->GetOutput();
   Atmosphere   = FDMExec->GetAtmosphere();
   Aerodynamics = FDMExec->GetAerodynamics();
   GroundReactions = FDMExec->GetGroundReactions();
index 8709b00b35d7418f2ea4b1252f28784eda92bd6d..f26b5465bb685bd599e2c3b9d8b5ac73a75d1448 100644 (file)
@@ -59,20 +59,19 @@ INCLUDES
 #include <string>
 #include <map>
 #include "FGJSBBase.h"
-#include "FGInitialCondition.h"
-#include "FGMatrix33.h"
-#include "FGColumnVector3.h"
-#include "FGQuaternion.h"
+#include <initialization/FGInitialCondition.h>
+#include <math/FGMatrix33.h>
+#include <math/FGColumnVector3.h>
+#include <math/FGQuaternion.h>
 #include "FGFDMExec.h"
-#include "FGAtmosphere.h"
-#include "FGFCS.h"
-#include "FGPropagate.h"
-#include "FGAuxiliary.h"
-#include "FGAerodynamics.h"
-#include "FGOutput.h"
-#include "FGAircraft.h"
-#include "FGGroundReactions.h"
-#include "FGPropulsion.h"
+#include <models/FGAtmosphere.h>
+#include <models/FGFCS.h>
+#include <models/FGPropagate.h>
+#include <models/FGAuxiliary.h>
+#include <models/FGAerodynamics.h>
+#include <models/FGAircraft.h>
+#include <models/FGGroundReactions.h>
+#include <models/FGPropulsion.h>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
@@ -117,12 +116,16 @@ public:
   /// Returns the simulation time in seconds.
   inline double Getsim_time(void) const { return sim_time; }
   /// Returns the simulation delta T.
-  inline double Getdt(void) { return dt; }
+  inline double Getdt(void) {
+    return dt;
+  }
 
   /// Suspends the simulation and sets the delta T to zero.
-  inline void Suspend(void) {saved_dt = dt; dt = 0.0;}
+  inline void SuspendIntegration(void) {saved_dt = dt; dt = 0.0;}
   /// Resumes the simulation by resetting delta T to the correct value.
-  inline void Resume(void)  {dt = saved_dt;}
+  inline void ResumeIntegration(void)  {dt = saved_dt;}
+
+  bool IntegrationSuspended(void) {return dt == 0.0;}
 
   /** Sets the current sim time.
       @param cur_time the current time
@@ -136,7 +139,9 @@ public:
   /** Sets the integration time step for the simulation executive.
       @param delta_t the time step in seconds.
       */
-  inline void  Setdt(double delta_t) { dt = delta_t; }
+  inline void  Setdt(double delta_t) {
+    dt = delta_t;
+  }
 
   /** Increments the simulation time.
       @return the new simulation time.
@@ -174,7 +179,6 @@ private:
 
   FGAircraft* Aircraft;
   FGPropagate* Propagate;
-  FGOutput* Output;
   FGAtmosphere* Atmosphere;
   FGFCS* FCS;
   FGAerodynamics* Aerodynamics;
diff --git a/src/FDM/JSBSim/FGTable.cpp b/src/FDM/JSBSim/FGTable.cpp
deleted file mode 100644 (file)
index b2b869d..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGTable.cpp
- Author:       Jon S. Berndt
- Date started: 1/9/2001
- Purpose:      Models a lookup table
-
- ------------- Copyright (C) 2001  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
---------------------------------------------------------------------------------
-Models a lookup table
-
-HISTORY
---------------------------------------------------------------------------------
-JSB  1/9/00          Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGTable.h"
-
-#if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
-#include <iomanip.h>
-#else
-#include <iomanip>
-#endif
-
-using namespace std;
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_TABLE;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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));
-  lastRowIndex=lastColumnIndex=2;
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols)
-{
-  if (NCols > 1) {
-    Type = tt2D;
-    colCounter = 1;
-    rowCounter = 0;
-  } else if (NCols == 1) {
-    Type = tt1D;
-    colCounter = 0;
-    rowCounter = 1;
-  } else {
-    cerr << "FGTable cannot accept 'Rows=0'" << endl;
-  }
-
-  Data = Allocate();
-  lastRowIndex=lastColumnIndex=2;
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTable::FGTable(int NRows) : nRows(NRows), nCols(1)
-{
-  Type = tt1D;
-  colCounter = 0;
-  rowCounter = 1;
-
-  Data = Allocate();
-  Debug(0);
-  lastRowIndex=lastColumnIndex=2;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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];
-  for (int r=0; r<=nRows; r++) {
-    Data[r] = new double[nCols+1];
-    for (int c=0; c<=nCols; c++) {
-      Data[r][c] = 0.0;
-    }
-  }
-  return Data;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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
-  //end-of-table value, do not extrapolate
-  if( key <= Data[1][0] ) {
-    lastRowIndex=2;
-    //cout << "Key underneath table: " << key << endl;
-    return Data[1][1];
-  } else if ( key >= Data[nRows][0] ) {
-    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;
-  // 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;
-    if (Factor > 1.0) Factor = 1.0;
-  } else {
-    Factor = 1.0;
-  }
-
-  Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1];
-
-  return Value;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-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 ) {
-//    cout << Data[r][0] << endl;
-    while ( r <= nRows && Data[r][0] <= rowKey ) { r++; }
-    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;
-  }
-
-  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]);
-
-  if (rFactor > 1.0) rFactor = 1.0;
-  else if (rFactor < 0.0) rFactor = 0.0;
-
-  if (cFactor > 1.0) cFactor = 1.0;
-  else if (cFactor < 0.0) cFactor = 0.0;
-
-  col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1];
-  col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c];
-
-  Value = col1temp + cFactor*(col2temp - col1temp);
-
-  return Value;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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-2].GetValue(rowKey, colKey);
-
-  return Value;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTable::operator<<(FGConfigFile& infile)
-{
-  int startRow=0;
-  int startCol=0;
-  int tableCtr=0;
-
-  if (Type == tt1D || Type == tt3D) startRow = 1;
-  if (Type == tt3D) startCol = 1;
-
-  for (int r=startRow; r<=nRows; r++) {
-    for (int c=startCol; c<=nCols; c++) {
-      if (r != 0 || c != 0) {
-        infile >> Data[r][c];
-        if (Type == tt3D) {
-          Tables[tableCtr] << infile;
-          tableCtr++;
-        }
-      }
-    }
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTable& FGTable::operator<<(const double n)
-{
-  Data[rowCounter][colCounter] = n;
-  if (colCounter == nCols) {
-    colCounter = 0;
-    rowCounter++;
-  } else {
-    colCounter++;
-  }
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTable& FGTable::operator<<(const int n)
-{
-  *this << (double)n;
-  return *this;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTable::Print(int spaces)
-{
-  string tabspace;
-  int startRow=0;
-  int startCol=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);
-#else
-  ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream
-#endif
-
-  for (int i=0;i<spaces;i++) tabspace+=" ";
-
-  cout.precision(4);
-  for (int r=startRow; r<=nRows; r++) {
-    cout << tabspace;
-    for (int c=startCol; c<=nCols; c++) {
-      if (r == 0 && c == 0) {
-        cout << "      ";
-      } else {
-        cout << Data[r][c] << "        ";
-        if (Type == tt3D) {
-          cout << endl;
-          Tables[r-1].Print(spaces);
-        }
-      }
-    }
-    cout << endl;
-  }
-  cout.setf(flags); // reset
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGTable::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: FGTable" << endl;
-    if (from == 1) cout << "Destroyed:    FGTable" << 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/FGTable.h b/src/FDM/JSBSim/FGTable.h
deleted file mode 100644 (file)
index 3c55073..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGTable.h
- Author:       Jon S. Berndt
- Date started: 1/9/2001
-
- ------------- Copyright (C) 2001  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
---------------------------------------------------------------------------------
-JSB  1/9/00          Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGTABLE_H
-#define FGTABLE_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGConfigFile.h"
-#include "FGJSBBase.h"
-#include <vector>
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_TABLE "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-using std::vector;
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Lookup table class.
-    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
-    @see FGPropeller
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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
-      the first row.  The implication of this layout is that there should
-      be no value in the upper left corner of the matrix e.g:
-      <pre>
-           0  10  20 30 ...
-      -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(int spaces=0);
-
-private:
-  enum type {tt1D, tt2D, tt3D} Type;
-  double** Data;
-  vector <FGTable> Tables;
-  int nRows, nCols, nTables;
-  int colCounter, rowCounter, tableCounter;
-  int lastRowIndex, lastColumnIndex, lastTableIndex;
-  double** Allocate(void);
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-#endif
-
diff --git a/src/FDM/JSBSim/FGTank.cpp b/src/FDM/JSBSim/FGTank.cpp
deleted file mode 100644 (file)
index f66fcbd..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGTank.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
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGTank.h"
-
-#if !defined ( sgi ) || defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
-using std::cerr;
-using std::endl;
-using std::cout;
-#endif
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_TANK;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-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");
-
-  if      (type == "FUEL")     Type = ttFUEL;
-  else if (type == "OXIDIZER") Type = ttOXIDIZER;
-  else                         Type = ttUNKNOWN;
-
-  AC_cfg->GetNextConfigLine();
-  while ((token = AC_cfg->GetValue()) != string("/AC_TANK")) {
-    if (token == "XLOC") *AC_cfg >> X;
-    else if (token == "YLOC") *AC_cfg >> Y;
-    else if (token == "ZLOC") *AC_cfg >> Z;
-    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;
-  }
-
-  vXYZ << X << Y << Z;
-
-  Selected = true;
-
-  if (Capacity != 0) {
-    PctFull = 100.0*Contents/Capacity;            // percent full; 0 to 100.0
-  } else {
-    Contents = 0;
-    PctFull  = 0;
-  }
-
-  if (Temperature != -9999.0)  Temperature = FahrenheitToCelsius(Temperature); 
-  Area = 40.0 * pow(Capacity/1975, 0.666666667);
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTank::~FGTank()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGTank::Drain(double used)
-{
-  double shortage = Contents - used;
-
-  if (shortage >= 0) {
-    Contents -= used;
-    PctFull = 100.0*Contents/Capacity;
-  } else {
-    Contents = 0.0;
-    PctFull = 0.0;
-    Selected = false;
-  }
-  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
-//       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 FGTank::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "      " << type << " tank holds " << Capacity << " lbs. " << type << endl;
-      cout << "      currently at " << PctFull << "% of maximum capacity" << endl;
-      cout << "      Tank location (X, Y, Z): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl;
-      cout << "      Effective radius: " << Radius << " inches" << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGTank" << endl;
-    if (from == 1) cout << "Destroyed:    FGTank" << 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/FGTank.h b/src/FDM/JSBSim/FGTank.h
deleted file mode 100644 (file)
index ec8ecbb..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGTank.h
- Author:       Jon S. Berndt
- Date started: 01/21/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.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-
-Based on Flightgear code, which is based on LaRCSim. This class simulates
-a generic Tank.
-
-HISTORY
---------------------------------------------------------------------------------
-01/21/99   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGTank_H
-#define FGTank_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGJSBBase.h"
-#include "FGConfigFile.h"
-#include "FGColumnVector3.h"
-#include "FGAuxiliary.h"
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  include STL_STRING
-  SG_USING_STD(string);
-  SG_USING_STD(cerr);
-  SG_USING_STD(endl);
-  SG_USING_STD(cout);
-#else
-# include <string>
-  using std::string;
-# if !defined(sgi) || defined(__GNUC__) || (_COMPILER_VERSION >= 740)
-   using std::cerr;
-   using std::endl;
-   using std::cout;
-# endif
-#endif
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_TANK "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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>
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGTank : public FGJSBBase
-{
-public:
-  FGTank(FGConfigFile*, FGFDMExec*);
-  ~FGTank();
-
-  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);}
-
-  double Fill(double amount);
-  void SetContents(double amount);
-  void SetTemperature(double temp) { Temperature = temp; }
-
-  enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER};
-
-private:
-  TankType Type;
-  string type;
-  FGColumnVector3 vXYZ;
-  double Capacity;
-  double Radius;
-  double PctFull;
-  double Contents;
-  double Area;
-  double Temperature;      
-  bool  Selected;
-  FGAuxiliary* Auxiliary;
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGThruster.cpp b/src/FDM/JSBSim/FGThruster.cpp
deleted file mode 100644 (file)
index 24904aa..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGThruster.cpp
- Author:       Jon S. Berndt
- Date started: 08/23/00
- Purpose:      Encapsulates the thruster object
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/23/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <sstream>
-
-#include "FGThruster.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_THRUSTER;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGThruster::FGThruster(FGFDMExec *FDMExec) : FGForce(FDMExec)
-{
-  Type = ttDirect;
-  SetTransformType(FGForce::tCustom);
-
-  EngineNum = 0;
-  PropertyManager = FDMExec->GetPropertyManager();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGThruster::FGThruster(FGFDMExec *FDMExec,
-                       FGConfigFile *Eng_cfg, int num ): FGForce(FDMExec)
-{
-  Type = ttDirect;
-  SetTransformType(FGForce::tCustom);
-  Name = Eng_cfg->GetValue();
-  GearRatio = 1.0;
-
-  EngineNum = num;
-  ThrustCoeff = 0.0;
-  ReverserAngle = 0.0;
-  PropertyManager = FDMExec->GetPropertyManager();
-
-  char property_name[80];
-  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
-  PropertyManager->Tie( property_name, &ThrustCoeff );
-  snprintf(property_name, 80, "propulsion/engine[%u]/reverser-angle", EngineNum);
-  PropertyManager->Tie( property_name, &ReverserAngle );
-
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGThruster::~FGThruster()
-{
-  char property_name[80];
-  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
-  PropertyManager->Untie( property_name );
-  snprintf(property_name, 80, "propulsion/engine[%u]/reverser-angle", EngineNum);
-  PropertyManager->Untie( property_name );
-
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGThruster::GetThrusterLabels(int id, string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << Name << "_Thrust[" << id << "]";
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGThruster::GetThrusterValues(int id, string delimeter)
-{
-  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
-//       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 FGThruster::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: FGThruster" << endl;
-    if (from == 1) cout << "Destroyed:    FGThruster" << 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/FGThruster.h b/src/FDM/JSBSim/FGThruster.h
deleted file mode 100644 (file)
index ff52358..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGThruster.h
- Author:       Jon S. Berndt
- Date started: 08/23/00
-
- ------------- Copyright (C) 2000  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
---------------------------------------------------------------------------------
-08/24/00  JSB  Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGTHRUSTER_H
-#define FGTHRUSTER_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGForce.h"
-#include "FGConfigFile.h"
-#include "FGPropertyManager.h"
-#include <string>
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_THRUSTER "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Base class for specific thrusting devices such as propellers, nozzles, etc.
-    @author Jon Berndt
-    @version $Id$
-    */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGThruster : public FGForce {
-
-public:
-  /// Constructor
-  FGThruster(FGFDMExec *FDMExec);
-  FGThruster(FGFDMExec *FDMExec, FGConfigFile *Eng_cfg, int num );
-  /// Destructor
-  virtual ~FGThruster();
-
-  enum eType {ttNozzle, ttRotor, ttPropeller, ttDirect};
-
-  virtual double Calculate(double tt) {
-       Thrust = tt;
-       vFn(1) = Thrust * cos(ReverserAngle);
-       return vFn(1);
-  }
-  void SetName(string name) {Name = name;}
-  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;}
-  virtual double GetRPM(void) { return 0.0; };
-  double GetGearRatio(void) {return GearRatio; }
-  virtual string GetThrusterLabels(int id, string delimeter);
-  virtual string GetThrusterValues(int id, string delimeter);
-  void SetReverserAngle(double radians) { ReverserAngle = radians; }
-  double GetReverserAngle(void) {return ReverserAngle;}
-
-
-  inline void SetThrustCoefficient(double ct) { ThrustCoeff = ct; }
-
-protected:
-  eType Type;
-  string Name;
-  double Thrust;
-  double PowerRequired;
-  double deltaT;
-  double GearRatio;
-  double ThrustCoeff;
-  double ReverserAngle;
-  int EngineNum;
-  FGPropertyManager* PropertyManager;
-  virtual void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGTrim.cpp b/src/FDM/JSBSim/FGTrim.cpp
deleted file mode 100644 (file)
index a4921e2..0000000
+++ /dev/null
@@ -1,684 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Header:       FGTrim.cpp
- Author:       Tony Peden
- Date started: 9/8/99
- --------- 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
---------------------------------------------------------------------------------
-9/8/99   TP   Created
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-This class takes the given set of IC's and finds the angle of attack, elevator,
-and throttle setting required to fly steady level. This is currently for in-air
-conditions only.  It is implemented using an iterative, one-axis-at-a-time
-scheme. */
-
-//  !!!!!!! BEWARE ALL YE WHO ENTER HERE !!!!!!!
-
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <stdlib.h>
-
-#include "FGFDMExec.h"
-#include "FGAtmosphere.h"
-#include "FGInitialCondition.h"
-#include "FGTrim.h"
-#include "FGAircraft.h"
-#include "FGMassBalance.h"
-#include "FGGroundReactions.h"
-#include "FGInertial.h"
-#include "FGAerodynamics.h"
-#include "FGColumnVector3.h"
-
-#if _MSC_VER
-#pragma warning (disable : 4786 4788)
-#endif
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_TRIM;
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) {
-
-  N=Nsub=0;
-  max_iterations=60;
-  max_sub_iterations=100;
-  Tolerance=1E-3;
-  A_Tolerance = Tolerance / 10;
-  
-  Debug=0;DebugLevel=0;
-  fdmex=FDMExec;
-  fgic=fdmex->GetIC();
-  total_its=0;
-  trimudot=true;
-  gamma_fallback=true;
-  axis_count=0;
-  mode=tt;
-  xlo=xhi=alo=ahi=0.0;
-  targetNlf=1.0;
-  debug_axis=tAll;
-  SetMode(tt);
-  if (debug_lvl & 2) cout << "Instantiated: FGTrim" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTrim::~FGTrim(void) {
-  for(current_axis=0; current_axis<TrimAxes.size(); current_axis++) {
-    delete TrimAxes[current_axis];
-  }
-  delete[] sub_iterations;
-  delete[] successful;
-  delete[] solution;
-  if (debug_lvl & 2) cout << "Destroyed:    FGTrim" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::TrimStats() {
-  char out[80];
-  int run_sum=0;
-  cout << endl << "  Trim Statistics: " << endl;
-  cout << "    Total Iterations: " << total_its << endl;
-  if(total_its > 0) {
-    cout << "    Sub-iterations:" << endl;
-    for(current_axis=0; current_axis<TrimAxes.size(); current_axis++) {
-      run_sum+=TrimAxes[current_axis]->GetRunCount();
-      snprintf(out,80,"   %5s: %3.0f average: %5.2f  successful: %3.0f  stability: %5.2f\n",
-                  TrimAxes[current_axis]->GetStateName().c_str(),
-                  sub_iterations[current_axis],
-                  sub_iterations[current_axis]/double(total_its),
-                  successful[current_axis],
-                  TrimAxes[current_axis]->GetAvgStability() );
-      cout << out;
-    }
-    cout << "    Run Count: " << run_sum << endl;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::Report(void) {
-  cout << "  Trim Results: " << endl;
-  for(current_axis=0; current_axis<TrimAxes.size(); current_axis++)
-    TrimAxes[current_axis]->AxisReport();
-
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::ClearStates(void) {
-    FGTrimAxis* ta;
-    
-    mode=tCustom;
-    vector<FGTrimAxis*>::iterator iAxes;
-    iAxes = TrimAxes.begin();
-    while (iAxes != TrimAxes.end()) {
-      ta=*iAxes;
-      delete ta;
-      iAxes++;
-    }
-    TrimAxes.clear();
-    //cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
-}
-    
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGTrim::AddState( State state, Control control ) {
-  FGTrimAxis* ta;
-  bool result=true;
-  
-  mode = tCustom;
-  vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
-  while (iAxes != TrimAxes.end()) {
-      ta=*iAxes;
-      if( ta->GetStateType() == state )
-        result=false;
-      iAxes++;
-  }
-  if(result) {
-    TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,state,control));
-    delete[] sub_iterations;
-    delete[] successful;
-    delete[] solution;
-    sub_iterations=new double[TrimAxes.size()];
-    successful=new double[TrimAxes.size()];
-    solution=new bool[TrimAxes.size()];
-  }
-  return result;
-}  
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGTrim::RemoveState( State state ) {
-  FGTrimAxis* ta;
-  bool result=false;
-  
-  mode = tCustom;
-  vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
-  while (iAxes != TrimAxes.end()) {
-      ta=*iAxes;
-      if( ta->GetStateType() == state ) {
-        delete ta;
-        TrimAxes.erase(iAxes);
-        result=true;
-        continue;
-      }
-      iAxes++;
-  }
-  if(result) {
-    delete[] sub_iterations;
-    delete[] successful;
-    delete[] solution;
-    sub_iterations=new double[TrimAxes.size()];
-    successful=new double[TrimAxes.size()];
-    solution=new bool[TrimAxes.size()];
-  }  
-  return result;
-}  
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGTrim::EditState( State state, Control new_control ){       
-  FGTrimAxis* ta;
-  bool result=false;
-  
-  mode = tCustom;
-  vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
-  while (iAxes != TrimAxes.end()) {
-      ta=*iAxes;
-      if( ta->GetStateType() == state ) {
-        TrimAxes.insert(iAxes,1,new FGTrimAxis(fdmex,fgic,state,new_control));
-        delete ta;
-        TrimAxes.erase(iAxes+1);
-        result=true;
-        break;
-      }
-      iAxes++;
-  }
-  return result;
-}  
-       
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGTrim::DoTrim(void) {
-  
-  trim_failed=false;
-  int i;
-
-  for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
-    fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false);
-  }
-
-  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++) {
-    //cout << current_axis << "  " << TrimAxes[current_axis]->GetStateName()
-    //<< "  " << TrimAxes[current_axis]->GetControlName()<< endl;
-    if(TrimAxes[current_axis]->GetStateType() == tQdot) {
-      if(mode == tGround) {
-         TrimAxes[current_axis]->initTheta();
-      }  
-    }  
-    xlo=TrimAxes[current_axis]->GetControlMin();
-    xhi=TrimAxes[current_axis]->GetControlMax();
-    TrimAxes[current_axis]->SetControl((xlo+xhi)/2);
-    TrimAxes[current_axis]->Run();
-    //TrimAxes[current_axis]->AxisReport();
-    sub_iterations[current_axis]=0;
-    successful[current_axis]=0;
-    solution[current_axis]=false;
-  }
-  
-  
-  if(mode == tPullup ) {
-    cout << "Setting pitch rate and nlf... " << endl;
-    setupPullup();
-    cout << "pitch rate done ... " << endl;
-    TrimAxes[0]->SetStateTarget(targetNlf);
-    cout << "nlf done" << endl;
-  } else if (mode == tTurn) {
-    setupTurn();
-    //TrimAxes[0]->SetStateTarget(targetNlf);
-  }  
-  
-  do {
-    axis_count=0;
-    for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
-      setDebug();
-      updateRates();
-      Nsub=0;
-      if(!solution[current_axis]) {
-        if(checkLimits()) { 
-          solution[current_axis]=true;
-          solve();
-        }  
-      } else if(findInterval()) {
-        solve();
-      } else {
-        solution[current_axis]=false;
-      }  
-      sub_iterations[current_axis]+=Nsub;
-    } 
-    for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
-      //these checks need to be done after all the axes have run
-      if(Debug > 0) TrimAxes[current_axis]->AxisReport();
-      if(TrimAxes[current_axis]->InTolerance()) {
-        axis_count++;
-        successful[current_axis]++;
-      } 
-    }
-    
-
-    if((axis_count == TrimAxes.size()-1) && (TrimAxes.size() > 1)) {
-      //cout << TrimAxes.size()-1 << " out of " << TrimAxes.size() << "!" << endl;
-      //At this point we can check the input limits of the failed axis
-      //and declare the trim failed if there is no sign change. If there
-      //is, keep going until success or max iteration count
-
-      //Oh, well: two out of three ain't bad
-      for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
-        //these checks need to be done after all the axes have run
-        if(!TrimAxes[current_axis]->InTolerance()) {
-          if(!checkLimits()) {
-            // special case this for now -- if other cases arise proper
-            // support can be added to FGTrimAxis
-            if( (gamma_fallback) &&
-                (TrimAxes[current_axis]->GetStateType() == tUdot) &&
-                (TrimAxes[current_axis]->GetControlType() == tThrottle)) {
-              cout << "  Can't trim udot with throttle, trying flight"
-              << " path angle. (" << N << ")" << endl;
-              if(TrimAxes[current_axis]->GetState() > 0)
-                TrimAxes[current_axis]->SetControlToMin();
-              else
-                TrimAxes[current_axis]->SetControlToMax();
-              TrimAxes[current_axis]->Run();
-              delete TrimAxes[current_axis];
-              TrimAxes[current_axis]=new FGTrimAxis(fdmex,fgic,tUdot,
-                                                    tGamma );
-            } else {
-              cout << "  Sorry, " << TrimAxes[current_axis]->GetStateName()
-              << " doesn't appear to be trimmable" << endl;
-              //total_its=k;
-              trim_failed=true; //force the trim to fail
-            } //gamma_fallback
-          }
-        } //solution check
-      } //for loop
-    } //all-but-one check
-    N++;
-    if(N > max_iterations)
-      trim_failed=true;
-  } while((axis_count < TrimAxes.size()) && (!trim_failed));
-  if((!trim_failed) && (axis_count >= TrimAxes.size())) {
-    total_its=N;
-    if (debug_lvl > 0)
-        cout << endl << "  Trim successful" << endl;
-  } else {
-    total_its=N;
-    if (debug_lvl > 0)
-        cout << endl << "  Trim failed" << endl;
-  }
-  for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
-    fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
-  }
-  fdmex->GetOutput()->Enable();
-  return !trim_failed;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGTrim::solve(void) {
-
-  double x1,x2,x3,f1,f2,f3,d,d0;
-  const double relax =0.9;
-  double eps=TrimAxes[current_axis]->GetSolverEps();
-
-  x1=x2=x3=0;
-  d=1;
-  bool success=false;
-  //initializations
-  if( solutionDomain != 0) {
-   /* if(ahi > alo) { */
-      x1=xlo;f1=alo;
-      x3=xhi;f3=ahi;
-   /* } else {
-      x1=xhi;f1=ahi;
-      x3=xlo;f3=alo;
-    }   */
-    d0=fabs(x3-x1);
-    //iterations
-    //max_sub_iterations=TrimAxes[current_axis]->GetIterationLimit();
-    while ( (TrimAxes[current_axis]->InTolerance() == false )
-             && (fabs(d) > eps) && (Nsub < max_sub_iterations)) {
-      Nsub++;
-      d=(x3-x1)/d0;
-      x2=x1-d*d0*f1/(f3-f1);
-      TrimAxes[current_axis]->SetControl(x2);
-      TrimAxes[current_axis]->Run();
-      f2=TrimAxes[current_axis]->GetState();
-      if(Debug > 1) {
-        cout << "FGTrim::solve Nsub,x1,x2,x3: " << Nsub << ", " << x1
-        << ", " << x2 << ", " << x3 << endl;
-        cout << "                             " << f1 << ", " << f2 << ", " << f3 << endl;
-      }
-      if(f1*f2 <= 0.0) {
-        x3=x2;
-        f3=f2;
-        f1=relax*f1;
-        //cout << "Solution is between x1 and x2" << endl;
-      }
-      else if(f2*f3 <= 0.0) {
-        x1=x2;
-        f1=f2;
-        f3=relax*f3;
-        //cout << "Solution is between x2 and x3" << endl;
-
-      }
-      //cout << i << endl;
-
-      
-    }//end while
-    if(Nsub < max_sub_iterations) success=true;
-  }  
-  return success;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/*
- produces an interval (xlo..xhi) on one side or the other of the current 
- control value in which a solution exists.  This domain is, hopefully, 
- smaller than xmin..0 or 0..xmax and the solver will require fewer iterations 
- to find the solution. This is, hopefully, more efficient than having the 
- solver start from scratch every time. Maybe it isn't though...
- This tries to take advantage of the idea that the changes from iteration to
- iteration will be small after the first one or two top-level iterations.
-
- assumes that changing the control will a produce significant change in the
- accel i.e. checkLimits() has already been called.
-
- if a solution is found above the current control, the function returns true 
- and xlo is set to the current control, xhi to the interval max it found, and 
- solutionDomain is set to 1.
- if the solution lies below the current control, then the function returns 
- true and xlo is set to the interval min it found and xmax to the current 
- control. if no solution is found, then the function returns false.
- in all cases, alo=accel(xlo) and ahi=accel(xhi) after the function exits.
- no assumptions about the state of the sim after this function has run 
- can be made.
-*/
-bool FGTrim::findInterval(void) {
-  bool found=false;
-  double step;
-  double current_control=TrimAxes[current_axis]->GetControl();
-  double current_accel=TrimAxes[current_axis]->GetState();;
-  double xmin=TrimAxes[current_axis]->GetControlMin();
-  double xmax=TrimAxes[current_axis]->GetControlMax();
-  double lastxlo,lastxhi,lastalo,lastahi;
-  
-  step=0.025*fabs(xmax);
-  xlo=xhi=current_control;
-  alo=ahi=current_accel;
-  lastxlo=xlo;lastxhi=xhi;
-  lastalo=alo;lastahi=ahi;
-  do {
-    
-    Nsub++;
-    step*=2;
-    xlo-=step;
-    if(xlo < xmin) xlo=xmin;
-    xhi+=step;
-    if(xhi > xmax) xhi=xmax;
-    TrimAxes[current_axis]->SetControl(xlo);
-    TrimAxes[current_axis]->Run();
-    alo=TrimAxes[current_axis]->GetState();
-    TrimAxes[current_axis]->SetControl(xhi);
-    TrimAxes[current_axis]->Run();
-    ahi=TrimAxes[current_axis]->GetState();
-    if(fabs(ahi-alo) <= TrimAxes[current_axis]->GetTolerance()) continue;
-    if(alo*ahi <=0) {  //found interval with root
-      found=true;
-      if(alo*current_accel <= 0) { //narrow interval down a bit
-        solutionDomain=-1;
-        xhi=lastxlo;
-        ahi=lastalo;
-        //xhi=current_control;
-        //ahi=current_accel;
-      } else {
-        solutionDomain=1;
-        xlo=lastxhi;
-        alo=lastahi;
-        //xlo=current_control;
-        //alo=current_accel;
-      }     
-    }
-    lastxlo=xlo;lastxhi=xhi;
-    lastalo=alo;lastahi=ahi;
-    if( !found && xlo==xmin && xhi==xmax ) continue;
-    if(Debug > 1)
-      cout << "FGTrim::findInterval: Nsub=" << Nsub << " Lo= " << xlo
-                           << " Hi= " << xhi << " alo*ahi: " << alo*ahi << endl;
-  } while(!found && (Nsub <= max_sub_iterations) );
-  return found;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//checks to see which side of the current control value the solution is on
-//and sets solutionDomain accordingly:
-//  1 if solution is between the current and max
-// -1 if solution is between the min and current
-//  0 if there is no solution
-// 
-//if changing the control produces no significant change in the accel then
-//solutionDomain is set to zero and the function returns false
-//if a solution is found, then xlo and xhi are set so that they bracket
-//the solution, alo is set to accel(xlo), and ahi is set to accel(xhi)
-//if there is no change or no solution then xlo=xmin, alo=accel(xmin) and
-//xhi=xmax and ahi=accel(xmax) 
-//in all cases the sim is left such that the control=xmax and accel=ahi
-
-bool FGTrim::checkLimits(void) {
-  bool solutionExists;
-  double current_control=TrimAxes[current_axis]->GetControl();
-  double current_accel=TrimAxes[current_axis]->GetState();
-  xlo=TrimAxes[current_axis]->GetControlMin();
-  xhi=TrimAxes[current_axis]->GetControlMax();
-
-  TrimAxes[current_axis]->SetControl(xlo);
-  TrimAxes[current_axis]->Run();
-  alo=TrimAxes[current_axis]->GetState();
-  TrimAxes[current_axis]->SetControl(xhi);
-  TrimAxes[current_axis]->Run();
-  ahi=TrimAxes[current_axis]->GetState();
-  if(Debug > 1)
-    cout << "checkLimits() xlo,xhi,alo,ahi: " << xlo << ", " << xhi << ", "
-                                              << alo << ", " << ahi << endl;
-  solutionDomain=0;
-  solutionExists=false;
-  if(fabs(ahi-alo) > TrimAxes[current_axis]->GetTolerance()) {
-    if(alo*current_accel <= 0) {
-      solutionExists=true;
-      solutionDomain=-1;
-      xhi=current_control;
-      ahi=current_accel;
-    } else if(current_accel*ahi < 0){
-      solutionExists=true;
-      solutionDomain=1;
-      xlo=current_control;
-      alo=current_accel;  
-    }
-  } 
-  TrimAxes[current_axis]->SetControl(current_control);
-  TrimAxes[current_axis]->Run();
-  return solutionExists;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::setupPullup() {
-  double g,q,cgamma;
-  g=fdmex->GetInertial()->gravity();
-  cgamma=cos(fgic->GetFlightPathAngleRadIC());
-  cout << "setPitchRateInPullup():  " << g << ", " << cgamma << ", "
-       << fgic->GetVtrueFpsIC() << endl;
-  q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
-  cout << targetNlf << ", " << q << endl;
-  fgic->SetQRadpsIC(q);
-  cout << "setPitchRateInPullup() complete" << endl;
-  
-}  
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::setupTurn(void){
-  double g,phi;
-  phi = fgic->GetRollAngleRadIC();
-  if( fabs(phi) > 0.001 && fabs(phi) < 1.56 ) {
-    targetNlf = 1 / cos(phi);
-    g = fdmex->GetInertial()->gravity(); 
-    psidot = g*tan(phi) / fgic->GetUBodyFpsIC();
-    cout << targetNlf << ", " << psidot << endl;
-  }
-   
-}  
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::updateRates(void){
-  if( mode == tTurn ) {
-    double phi = fgic->GetRollAngleRadIC();
-    double g = fdmex->GetInertial()->gravity(); 
-    double p,q,r,theta;
-    if(fabs(phi) > 0.001 && fabs(phi) < 1.56 ) {
-      theta=fgic->GetPitchAngleRadIC();
-      phi=fgic->GetRollAngleRadIC();
-      psidot = g*tan(phi) / fgic->GetUBodyFpsIC();
-      p=-psidot*sin(theta);
-      q=psidot*cos(theta)*sin(phi);
-      r=psidot*cos(theta)*cos(phi);
-    } else {
-      p=q=r=0;
-    }      
-    fgic->SetPRadpsIC(p);
-    fgic->SetQRadpsIC(q);
-    fgic->SetRRadpsIC(r);
-  } else if( mode == tPullup && fabs(targetNlf-1) > 0.01) {
-      double g,q,cgamma;
-      g=fdmex->GetInertial()->gravity();
-      cgamma=cos(fgic->GetFlightPathAngleRadIC());
-      q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
-      fgic->SetQRadpsIC(q);
-  }  
-}  
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::setDebug(void) {
-  if(debug_axis == tAll ||
-      TrimAxes[current_axis]->GetStateType() == debug_axis ) {
-    Debug=DebugLevel; 
-    return;
-  } else {
-    Debug=0;
-    return;
-  }
-}      
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTrim::SetMode(TrimMode tt) {
-    ClearStates();
-    mode=tt;
-    switch(tt) {
-      case tFull:
-        if (debug_lvl > 0)          
-          cout << "  Full Trim" << endl;
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
-        break;
-      case tLongitudinal:
-        if (debug_lvl > 0)          
-          cout << "  Longitudinal Trim" << endl;
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
-        break;
-      case tGround:
-        if (debug_lvl > 0)          
-          cout << "  Ground Trim" << endl;
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta ));
-        //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi ));
-        break;
-      case tPullup:
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
-        break;
-      case tTurn:
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
-        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
-        break;
-      case tCustom:
-      case tNone:
-        break;
-    }
-    //cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
-    sub_iterations=new double[TrimAxes.size()];
-    successful=new double[TrimAxes.size()];
-    solution=new bool[TrimAxes.size()];
-    current_axis=0;
-}    
-//YOU WERE WARNED, BUT YOU DID IT ANYWAY.
-}
diff --git a/src/FDM/JSBSim/FGTrim.h b/src/FDM/JSBSim/FGTrim.h
deleted file mode 100644 (file)
index 19647cc..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGTrim.h
- Author:       Tony Peden
- Date started: 7/1/99
-
- ------------- 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
---------------------------------------------------------------------------------
-9/8/99   TP   Created
-
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-
-This class takes the given set of IC's and finds the aircraft state required to
-maintain a specified flight condition.  This flight condition can be
-steady-level with non-zero sideslip, a steady turn, a pull-up or pushover.
-On-ground conditions can be trimmed as well, but this is currently limited to
-adjusting altitude and pitch angle only. It is implemented using an iterative,
-one-axis-at-a-time scheme.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGTRIM_H
-#define FGTRIM_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGFDMExec.h"
-#include "FGJSBBase.h"
-#include "FGTrimAxis.h"
-
-#include <vector>
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_TRIM "$Id$"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-  #define snprintf _snprintf
-#endif
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-typedef enum { tLongitudinal, tFull, tGround, tPullup,
-               tCustom, tNone, tTurn
-             } TrimMode;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** FGTrim -- the trimming routine for JSBSim.
-    FGTrim finds the aircraft attitude and control settings needed to maintain
-    the steady state described by the FGInitialCondition object .  It does this
-    iteratively by assigning a control to each state and adjusting that control
-    until the state is within a specified tolerance of zero. States include the
-    recti-linear accelerations udot, vdot, and wdot, the angular accelerations
-    qdot, pdot, and rdot, and the difference between heading and ground track.
-    Controls include the usual flight deck controls available to the pilot plus
-    angle of attack (alpha), sideslip angle(beta), flight path angle (gamma),
-    pitch attitude(theta), roll attitude(phi), and altitude above ground.  The
-    last three are used for on-ground trimming. The state-control pairs used in
-    a given trim are completely user configurable and several pre-defined modes
-    are provided as well. They are:
-    - tLongitudinal: Trim wdot with alpha, udot with thrust, qdot with elevator
-    - tFull: tLongitudinal + vdot with phi, pdot with aileron, rdot with rudder
-             and heading minus ground track (hmgt) with beta
-    - tPullup: tLongitudinal but adjust alpha to achieve load factor input
-               with SetTargetNlf()
-    - tGround: wdot with altitude, qdot with theta, and pdot with phi
-
-    The remaining modes include <b>tCustom</b>, which is completely user defined and
-    <b>tNone</b>.
-
-    Note that trims can (and do) fail for reasons that are completely outside
-    the control of the trimming routine itself. The most common problem is the
-    initial conditions: is the model capable of steady state flight
-    at those conditions?  Check the speed, altitude, configuration (flaps,
-    gear, etc.), weight, cg, and anything else that may be relevant.
-
-    Example usage:<pre>
-    FGFDMExec* FDMExec = new FGFDMExec();
-
-    FGInitialCondition* fgic = new FGInitialCondition(FDMExec);
-    FGTrim fgt(FDMExec, fgic, tFull);
-    fgic->SetVcaibratedKtsIC(100);
-    fgic->SetAltitudeFtIC(1000);
-    fgic->SetClimbRate(500);
-    if( !fgt.DoTrim() ) {
-      cout << "Trim Failed" << endl;
-    }
-    fgt.Report(); </pre>
-    @author Tony Peden
-    @version "$Id$"
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGTrim : public FGJSBBase
-{
-private:
-
-  vector<FGTrimAxis*> TrimAxes;
-  unsigned int current_axis;
-  int N, Nsub;
-  TrimMode mode;
-  int DebugLevel, Debug;
-  double Tolerance, A_Tolerance;
-  double wdot,udot,qdot;
-  double dth;
-  double *sub_iterations;
-  double *successful;
-  bool *solution;
-  int max_sub_iterations;
-  int max_iterations;
-  int total_its;
-  bool trimudot;
-  bool gamma_fallback;
-  bool trim_failed;
-  unsigned int axis_count;
-  int solutionDomain;
-  double xlo,xhi,alo,ahi;
-  double targetNlf;
-  int debug_axis;
-
-  double psidot,thetadot;
-
-  FGFDMExec* fdmex;
-  FGInitialCondition* fgic;
-
-  bool solve(void);
-
-  /** @return false if there is no change in the current axis accel
-      between accel(control_min) and accel(control_max). If there is a
-      change, sets solutionDomain to:
-      0 for no sign change,
-     -1 if sign change between accel(control_min) and accel(0)
-      1 if sign between accel(0) and accel(control_max)
-  */
-  bool findInterval(void);
-
-  bool checkLimits(void);
-
-  void setupPullup(void);
-  void setupTurn(void);
-
-  void updateRates(void);
-
-  void setDebug(void);
-
-public:
-  /** Initializes the trimming class
-      @param FDMExec pointer to a JSBSim executive object.
-      @param tm trim mode
-  */
-  FGTrim(FGFDMExec *FDMExec, TrimMode tm=tGround );
-
-  ~FGTrim(void);
-
-  /** Execute the trim
-  */
-  bool DoTrim(void);
-
-  /** Print the results of the trim. For each axis trimmed, this
-      includes the final state value, control value, and tolerance
-      used.
-      @return true if trim succeeds
-  */
-  void Report(void);
-
-  /** Iteration statistics
-  */
-  void TrimStats();
-
-  /** Clear all state-control pairs and set a predefined trim mode
-      @param tm the set of axes to trim. Can be:
-             tLongitudinal, tFull, tGround, tCustom, or tNone
-  */
-  void SetMode(TrimMode tm);
-
-  /** Clear all state-control pairs from the current configuration.
-      The trimming routine must have at least one state-control pair
-      configured to be useful
-  */
-  void ClearStates(void);
-
-  /** Add a state-control pair to the current configuration. See the enums
-      State and Control in FGTrimAxis.h for the available options.
-      Will fail if the given state is already configured.
-      @param state the accel or other condition to zero
-      @param control the control used to zero the state
-      @return true if add is successful
-  */
-  bool AddState( State state, Control control );
-
-  /** Remove a specific state-control pair from the current configuration
-      @param state the state to remove
-      @return true if removal is successful
-  */
-  bool RemoveState( State state );
-
-  /** Change the control used to zero a state previously configured
-      @param state the accel or other condition to zero
-      @param new_control the control used to zero the state
-  */
-  bool EditState( State state, Control new_control );
-
-  /** automatically switch to trimming longitudinal acceleration with
-      flight path angle (gamma) once it becomes apparent that there
-      is not enough/too much thrust.
-      @param bb true to enable fallback
-  */
-  inline void SetGammaFallback(bool bb) { gamma_fallback=bb; }
-
-  /** query the fallback state
-      @return true if fallback is enabled.
-  */
-  inline bool GetGammaFallback(void) { return gamma_fallback; }
-
-  /** Set the iteration limit. DoTrim() will return false if limit
-      iterations are reached before trim is achieved.  The default
-      is 60.  This does not ordinarily need to be changed.
-      @param ii integer iteration limit
-  */
-  inline void SetMaxCycles(int ii) { max_iterations = ii; }
-
-  /** Set the per-axis iteration limit.  Attempt to zero each state
-      by iterating limit times before moving on to the next. The
-      default limit is 100 and also does not ordinarily need to
-      be changed.
-      @param ii integer iteration limit
-  */
-  inline void SetMaxCyclesPerAxis(int ii) { max_sub_iterations = ii; }
-
-  /** Set the tolerance for declaring a state trimmed. Angular accels are
-      held to a tolerance of 1/10th of the given.  The default is
-      0.001 for the recti-linear accelerations and 0.0001 for the angular.
-  */
-  inline void SetTolerance(double tt) {
-    Tolerance = tt;
-    A_Tolerance = tt / 10;
-  }
-
-  /**
-    Debug level 1 shows results of each top-level iteration
-    Debug level 2 shows level 1 & results of each per-axis iteration
-  */
-  inline void SetDebug(int level) { DebugLevel = level; }
-  inline void ClearDebug(void) { DebugLevel = 0; }
-
-  /**
-    Output debug data for one of the axes
-    The State enum is defined in FGTrimAxis.h
-  */
-  inline void DebugState(State state) { debug_axis=state; }
-
-  inline void SetTargetNlf(double nlf) { targetNlf=nlf; }
-  inline double GetTargetNlf(void) { return targetNlf; }
-
-};
-}
-
-#endif
diff --git a/src/FDM/JSBSim/FGTrimAxis.cpp b/src/FDM/JSBSim/FGTrimAxis.cpp
deleted file mode 100644 (file)
index 7dd9682..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef _MSC_VER
-#  pragma warning (disable : 4786)
-#endif
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <string>
-#include <stdlib.h>
-
-#include "FGFDMExec.h"
-#include "FGAtmosphere.h"
-#include "FGInitialCondition.h"
-#include "FGTrimAxis.h"
-#include "FGAircraft.h"
-#include "FGPropulsion.h"
-#include "FGAerodynamics.h"
-
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_TRIMAXIS;
-
-/*****************************************************************************/
-
-FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
-                       Control ctrl) {
-
-  fdmex=fdex;
-  fgic=ic;
-  state=st;
-  control=ctrl;
-  max_iterations=10;
-  control_value=0;
-  its_to_stable_value=0;
-  total_iterations=0;
-  total_stability_iterations=0;
-  state_convert=1.0;
-  control_convert=1.0;
-  state_value=0;
-  state_target=0;
-  switch(state) {
-    case tUdot: tolerance = DEFAULT_TOLERANCE; break;
-    case tVdot: tolerance = DEFAULT_TOLERANCE; break;
-    case tWdot: tolerance = DEFAULT_TOLERANCE; break;
-    case tQdot: tolerance = DEFAULT_TOLERANCE / 10; break;
-    case tPdot: tolerance = DEFAULT_TOLERANCE / 10; break;
-    case tRdot: tolerance = DEFAULT_TOLERANCE / 10; break;
-    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:
-    control_min=0;
-    control_max=1;
-    control_value=0.5;
-    break;
-  case tBeta:
-    control_min=-30*degtorad;
-    control_max=30*degtorad;
-    control_convert=radtodeg;
-    break;
-  case tAlpha:
-    control_min=fdmex->GetAerodynamics()->GetAlphaCLMin();
-    control_max=fdmex->GetAerodynamics()->GetAlphaCLMax();
-    if(control_max <= control_min) {
-      control_max=20*degtorad;
-      control_min=-5*degtorad;
-    }
-    control_value= (control_min+control_max)/2;
-    control_convert=radtodeg;
-    solver_eps=tolerance/100;
-    break;
-  case tPitchTrim:
-  case tElevator:
-  case tRollTrim:
-  case tAileron:
-  case tYawTrim:
-  case tRudder:
-    control_min=-1;
-    control_max=1;
-    state_convert=radtodeg;
-    solver_eps=tolerance/100;
-    break;
-  case tAltAGL:
-    control_min=0;
-    control_max=30;
-    control_value=fdmex->GetPropagate()->GetDistanceAGL();
-    solver_eps=tolerance/100;
-    break;
-  case tTheta:
-    control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad;
-    control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad;
-    state_convert=radtodeg;
-    break;
-  case tPhi:
-    control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad;
-    control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad;
-    state_convert=radtodeg;
-    control_convert=radtodeg;
-    break;
-  case tGamma:
-    solver_eps=tolerance/100;
-    control_min=-80*degtorad;
-    control_max=80*degtorad;
-    control_convert=radtodeg;
-    break;
-  case tHeading:
-    control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad;
-    control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad;
-    state_convert=radtodeg;
-    break;
-  }
-
-
-  Debug(0);
-}
-
-/*****************************************************************************/
-
-FGTrimAxis::~FGTrimAxis(void)
-{
-  Debug(1);
-}
-
-/*****************************************************************************/
-
-void FGTrimAxis::getState(void) {
-  switch(state) {
-  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;
-  }
-}
-
-/*****************************************************************************/
-
-//States are not settable
-
-void FGTrimAxis::getControl(void) {
-  switch(control) {
-  case tThrottle:  control_value=fdmex->GetFCS()->GetThrottleCmd(0); 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->GetPropagate()->GetDistanceAGL();break;
-  case tTheta:     control_value=fdmex->GetPropagate()->GetEuler(eTht); break;
-  case tPhi:       control_value=fdmex->GetPropagate()->GetEuler(ePhi); break;
-  case tGamma:     control_value=fdmex->GetAuxiliary()->GetGamma();break;
-  case tHeading:   control_value=fdmex->GetPropagate()->GetEuler(ePsi); break;
-  }
-}
-
-/*****************************************************************************/
-
-double FGTrimAxis::computeHmgt(void) {
-  double diff;
-
-  diff   = fdmex->GetPropagate()->GetEuler(ePsi) -
-             fdmex->GetAuxiliary()->GetGroundTrack();
-
-  if( diff < -M_PI ) {
-     return (diff + 2*M_PI);
-  } else if( diff > M_PI ) {
-     return (diff - 2*M_PI);
-  } else {
-     return diff;
-  }
-
-}
-
-/*****************************************************************************/
-
-
-void FGTrimAxis::setControl(void) {
-  switch(control) {
-  case tThrottle:  setThrottlesPct(); break;
-  case tBeta:      fgic->SetBetaRadIC(control_value); break;
-  case tAlpha:     fgic->SetAlphaRadIC(control_value);  break;
-  case tPitchTrim: fdmex->GetFCS()->SetPitchTrimCmd(control_value); break;
-  case tElevator:  fdmex->GetFCS()->SetDeCmd(control_value); break;
-  case tRollTrim:
-  case tAileron:   fdmex->GetFCS()->SetDaCmd(control_value); break;
-  case tYawTrim:
-  case tRudder:    fdmex->GetFCS()->SetDrCmd(control_value); break;
-  case tAltAGL:    fgic->SetAltitudeAGLFtIC(control_value); break;
-  case tTheta:     fgic->SetPitchAngleRadIC(control_value); break;
-  case tPhi:       fgic->SetRollAngleRadIC(control_value); break;
-  case tGamma:     fgic->SetFlightPathAngleRadIC(control_value); break;
-  case tHeading:   fgic->SetTrueHeadingRadIC(control_value); break;
-  }
-}
-
-
-
-
-
-/*****************************************************************************/
-
-// 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
-// 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 )
-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
-  // that's in contact with the ground.
-  i=0; ref=-1; center=-1;
-  while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) {
-    if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) {
-      if(fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)
-        ref=i;
-      else
-        center=i;
-    }
-    i++;
-  }
-  if((ref < 0) && (center >= 0)) {
-    ref=center;
-  }
-  cout << "SetThetaOnGround ref gear: " << ref << endl;
-  if(ref >= 0) {
-    double sp = fdmex->GetPropagate()->GetSinEuler(ePhi);
-    double cp = fdmex->GetPropagate()->GetCosEuler(ePhi);
-    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;
-}
-
-/*****************************************************************************/
-
-bool FGTrimAxis::initTheta(void) {
-  int i,N;
-  int iForward = 0;
-  int iAft = 1;
-  double zAft,zForward,zDiff,theta;
-  double xAft,xForward,xDiff;
-  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++ ) {
-    if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) {
-        iForward=i;
-        break;
-    }
-  }
-  //now find the first wheel unit aft of the cg
-  for( i=0; i<N; i++ ) {
-    if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) {
-        iAft=i;
-        break;
-    }
-  }
-
-  // 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 << i << endl;
-  if (debug_lvl > 0) {
-      cout << "    Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*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)
-    return true;
-  else
-    return false;
-}
-
-/*****************************************************************************/
-
-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()) &&
-      (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01))
-        ref=i;
-    i++;
-  }
-  if (ref >= 0) {
-    double st = fdmex->GetPropagate()->GetSinEuler(eTht);
-    double ct = fdmex->GetPropagate()->GetCosEuler(eTht);
-    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);
-
-}
-
-/*****************************************************************************/
-
-void FGTrimAxis::Run(void) {
-
-  double last_state_value;
-  int i;
-  setControl();
-  //cout << "FGTrimAxis::Run: " << control_value << endl;
-  i=0;
-  bool stable=false;
-  while(!stable) {
-    i++;
-    last_state_value=state_value;
-    fdmex->RunIC();
-    getState();
-    if(i > 1) {
-      if((fabs(last_state_value - state_value) < tolerance) || (i >= 100) )
-        stable=true;
-    }
-  }
-
-  its_to_stable_value=i;
-  total_stability_iterations+=its_to_stable_value;
-  total_iterations++;
-}
-
-/*****************************************************************************/
-
-void FGTrimAxis::setThrottlesPct(void) {
-  double tMin,tMax;
-  for(unsigned i=0;i<fdmex->GetPropulsion()->GetNumEngines();i++) {
-      tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin();
-      tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax();
-      //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value;
-      fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin));
-      //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl;
-      fdmex->RunIC(); //apply throttle change
-      fdmex->GetPropulsion()->GetSteadyState();
-  }
-}
-
-/*****************************************************************************/
-
-void FGTrimAxis::AxisReport(void) {
-
-  char out[80];
-
-  sprintf(out,"  %20s: %6.2f %5s: %9.2e Tolerance: %3.0e",
-           GetControlName().c_str(), GetControl()*control_convert,
-           GetStateName().c_str(), GetState()+state_target, GetTolerance());
-  cout << out;
-
-  if( fabs(GetState()+state_target) < fabs(GetTolerance()) )
-     cout << "  Passed" << endl;
-  else
-     cout << "  Failed" << endl;
-}
-
-/*****************************************************************************/
-
-double FGTrimAxis::GetAvgStability( void ) {
-  if(total_iterations > 0) {
-    return double(total_stability_iterations)/double(total_iterations);
-  }
-  return 0;
-}
-
-/*****************************************************************************/
-//    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 FGTrimAxis::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: FGTrimAxis" << endl;
-    if (from == 1) cout << "Destroyed:    FGTrimAxis" << 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/FGTrimAxis.h b/src/FDM/JSBSim/FGTrimAxis.h
deleted file mode 100644 (file)
index e0754a0..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Header:       FGTrimAxis.h
- 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
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGTRIMAXIS_H
-#define FGTRIMAXIS_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <string>
-
-#include "FGFDMExec.h"
-#include "FGJSBBase.h"
-#include "FGInitialCondition.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_TRIMAXIS "$Id$"
-
-#define DEFAULT_TOLERANCE 0.001
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-const string StateNames[10]=   { "all","udot","vdot","wdot","qdot","pdot","rdot",
-                                "hmgt","nlf" 
-                              };
-const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack",
-                                 "Elevator","Ailerons","Rudder",
-                                 "Altitude AGL", "Pitch Angle",
-                                 "Roll Angle", "Flight Path Angle", 
-                                 "Pitch Trim", "Roll Trim", "Yaw Trim",
-                                 "Heading"
-                               };
-
-class FGInitialCondition;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models an aircraft axis for purposes of trimming.
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-enum State { tAll,tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt,tNlf };
-enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL,
-               tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading };
-
-class FGTrimAxis : public FGJSBBase
-{
-public:
-  FGTrimAxis(FGFDMExec* fdmex, 
-             FGInitialCondition *ic, 
-             State st,
-             Control ctrl );
-  ~FGTrimAxis();
-
-  void Run(void);
-  double GetState(void) { getState(); return state_value; }
-  //Accels are not settable
-  inline void SetControl(double value ) { control_value=value; }
-  inline double GetControl(void) { return control_value; }
-
-  inline State GetStateType(void) { return state; }
-  inline Control GetControlType(void) { return control; }
-
-  inline string GetStateName(void) { return StateNames[state]; }
-  inline string GetControlName(void) { return ControlNames[control]; }
-
-  inline double GetControlMin(void) { return control_min; }
-  inline double GetControlMax(void) { return control_max; }
-
-  inline void SetControlToMin(void) { control_value=control_min; }
-  inline void SetControlToMax(void) { control_value=control_max; }
-  
-  inline void SetControlLimits(double min, double max) { 
-      control_min=min;
-      control_max=max;
-  }    
-
-  inline void  SetTolerance(double ff) { tolerance=ff;}
-  inline double GetTolerance(void) { return tolerance; }
-
-  inline double GetSolverEps(void) { return solver_eps; }
-  inline void SetSolverEps(double ff) { solver_eps=ff; }
-
-  inline int  GetIterationLimit(void) { return max_iterations; }
-  inline void SetIterationLimit(int ii) { max_iterations=ii; }
-
-  inline int GetStability(void) { return its_to_stable_value; }
-  inline int GetRunCount(void) { return total_stability_iterations; }
-  double GetAvgStability( void );
-  
-  void SetThetaOnGround(double ff);
-  void SetPhiOnGround(double ff);
-  
-  inline void SetStateTarget(double target) { state_target=target; }
-  inline double GetStateTarget(void) { return state_target; }
-  
-  bool initTheta(void);
-  
-  void AxisReport(void);
-  
-  bool InTolerance(void) { getState(); return (fabs(state_value) <= tolerance); }
-
-private:
-  FGFDMExec *fdmex;
-  FGInitialCondition *fgic;
-
-  State   state;
-  Control control;
-  
-  double state_target;
-  
-  double state_value;
-  double control_value;
-
-  double control_min;
-  double control_max;
-
-  double tolerance;
-
-  double solver_eps;
-
-  double state_convert;
-  double control_convert;
-
-  int max_iterations;
-
-  int its_to_stable_value;
-  int total_stability_iterations;
-  int total_iterations;
-
-  void setThrottlesPct(void);
-
-  void getState(void);
-  void getControl(void);
-  void setControl(void);
-  
-  double computeHmgt(void);
-  
-  void Debug(int from);
-};
-}
-#endif
diff --git a/src/FDM/JSBSim/FGTurbine.cpp b/src/FDM/JSBSim/FGTurbine.cpp
deleted file mode 100644 (file)
index 03c6a35..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGTurbine.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
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <vector>
-#include <sstream>
-
-#include "FGTurbine.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_TURBINE;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGTurbine::FGTurbine(FGFDMExec* exec, FGConfigFile* cfg, int engine_number)
-  : FGEngine(exec, engine_number)
-{
-  SetDefaults();
-
-  Load(cfg);
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGTurbine::~FGTurbine()
-{
-  unbind();
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// The main purpose of Calculate() is to determine what phase the engine should
-// be in, then call the corresponding function.
-
-double FGTurbine::Calculate(void)
-{
-  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 {
-    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();
-  }
-
-  // The thruster can modify the thrust, eg. thrust reverser
-  return Thrust = Thruster->Calculate(Thrust);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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::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 * (0.84 + (1-N2norm)*(1-N2norm));
-    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 (AugMethod == 2) {
-    if (AugmentCmd > 0.0) {
-      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 {
-      Augmentation = false;
-    }
-  }
-
-  if ((Injected == 1) && Injection) {
-     thrust = thrust * ThrustTables[3]->TotalValue();
-  }
-
-  ConsumeFuel();
-  if (Cutoff) phase = tpOff;
-  if (Starved) phase = tpOff;
-
-  return thrust;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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;
-      ConsumeFuel();
-      }
-    else {
-      phase = tpRun;
-      Running = true;
-      Starter = false;
-      Cranking = false;
-      }
-    }
-  else {                 // no start if N2 < 15%
-    phase = tpOff;
-    Starter = false;
-    }
-
-  return 0.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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);
-  ConsumeFuel();
-  if (ThrottlePos < 0.01) phase = tpRun;        // clear the stall with throttle
-
-  return 0.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGTurbine::Seize(void)
-{
-    double qbar = Auxiliary->Getqbar();
-    N2 = 0.0;
-    N1 = Seek(&N1, qbar/20.0, 0, N1/15.0);
-    FuelFlow_pph = IdleFF;
-    ConsumeFuel();
-    OilPressure_psi = 0.0;
-    OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0, 0.2);
-    Running = false;
-    return 0.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGTurbine::CalcFuelNeed(void)
-{
-  return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-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)
-{
-  string token;
-
-  Name = Eng_cfg->GetValue("NAME");
-  Eng_cfg->GetNextConfigLine();
-  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;
-    if (token == "EOF") return false;
-  }
-
-  // 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
-
-  bindmodel();
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGTurbine::GetEngineLabels(string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << Name << "_N1[" << EngineNumber << "]" << delimeter
-      << Name << "_N2[" << EngineNumber << "]" << delimeter
-      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-string FGTurbine::GetEngineValues(string delimeter)
-{
-  std::ostringstream buf;
-
-  buf << N1 << delimeter
-      << N2 << delimeter
-      << Thruster->GetThrusterValues(EngineNumber, delimeter);
-
-  return buf.str();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTurbine::bindmodel()
-{
-  char property_name[80];
-
-  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
-  PropertyManager->Tie( property_name, &N1);
-  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
-  PropertyManager->Tie( property_name, &N2);
-  snprintf(property_name, 80, "propulsion/engine[%u]/fuel-flow", EngineNumber);
-  PropertyManager->Tie( property_name, &FuelFlow_pph);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGTurbine::unbind()
-{
-  char property_name[80];
-
-  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
-  PropertyManager->Untie(property_name);
-  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
-  PropertyManager->Untie(property_name);
-  snprintf(property_name, 80, "propulsion/engine[%u]/fuel-flow", EngineNumber);
-  PropertyManager->Untie( property_name);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGTurbine::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: FGTurbine" << endl;
-    if (from == 1) cout << "Destroyed:    FGTurbine" << 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/FGTurbine.h b/src/FDM/JSBSim/FGTurbine.h
deleted file mode 100644 (file)
index 5f685e6..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGTurbine.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
-04/29/2004  DPC  Renamed from FGSimTurbine to FGTurbine
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGTURBINE_H
-#define FGTURBINE_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <vector>
-#include "FGEngine.h"
-#include "FGConfigFile.h"
-#include "FGCoefficient.h"
-
-#define ID_TURBINE "$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_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
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGTurbine : public FGEngine
-{
-public:
-  /** Constructor
-      @param Executive pointer to executive structure
-      @param Eng_cfg pointer to engine config file instance
-      @param engine_number engine number*/
-  FGTurbine(FGFDMExec* Executive, FGConfigFile* Eng_cfg, int engine_number);
-  /// Destructor
-  ~FGTurbine();
-
-  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(string delimeter);
-  string GetEngineValues(string delimeter);
-
-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 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();
-  double SpinUp(void);
-  double Start(void);
-  double Stall(void);
-  double Seize(void);
-  double Trim();
-
-  void SetDefaults(void);
-  bool Load(FGConfigFile *ENG_cfg);
-  void bindmodel(void);
-  void unbind(void);
-  void Debug(int from);
-
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
-
diff --git a/src/FDM/JSBSim/FGfdmSocket.cpp b/src/FDM/JSBSim/FGfdmSocket.cpp
deleted file mode 100644 (file)
index c6672a7..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGfdmSocket.cpp
- Author:       Jon S. Berndt
- Date started: 11/08/99
- Purpose:      Encapsulates a socket
- Called by:    FGOutput, 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 excapsulates a socket for simple data writing
-
-HISTORY
---------------------------------------------------------------------------------
-11/08/99   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGfdmSocket.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_FDMSOCKET;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGfdmSocket::FGfdmSocket(string address, int port)
-{
-  size = 0;
-  connected = false;
-
-  #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
-    WSADATA wsaData;
-    int wsaReturnCode;
-    wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
-    if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
-    else cout << "Winsock DLL not initialized ..." << endl;
-  #endif
-
-  if (address.find_first_not_of("0123456789.",0) != address.npos) {
-    if ((host = gethostbyname(address.c_str())) == NULL) {
-      cout << "Could not get host net address by name..." << endl;
-    }
-  } else {
-    if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) {
-      cout << "Could not get host net address by number..." << endl;
-    }
-  }
-
-  if (host != NULL) {
-    cout << "Got host net address..." << endl;
-    sckt = socket(AF_INET, SOCK_STREAM, 0);
-
-    if (sckt >= 0) {  // successful
-      memset(&scktName, 0, sizeof(struct sockaddr_in));
-      scktName.sin_family = AF_INET;
-      scktName.sin_port = htons(port);
-      memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
-      int len = sizeof(struct sockaddr_in);
-      if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) {   // successful
-        cout << "Successfully connected to socket ..." << endl;
-        connected = true;
-      } else {                // unsuccessful
-        cout << "Could not connect to socket ..." << endl;
-      }
-    } else {          // unsuccessful
-      cout << "Could not create socket for FDM, error = " << errno << endl;
-    }
-  }
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGfdmSocket::~FGfdmSocket()
-{
-  #ifndef macintosh
-  if (sckt) shutdown(sckt,2);
-  #endif
-  
-  #ifdef __BORLANDC__
-    WSACleanup();
-  #endif
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGfdmSocket::Clear(void)
-{
-  buffer = "";
-  size = 0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGfdmSocket::Append(const char* item)
-{
-  if (size == 0) buffer += string(item);
-  else buffer += string(",") + string(item);
-  size++;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGfdmSocket::Append(double item)
-{
-  char s[25];
-
-  sprintf(s,"%12.7f",item);
-
-  if (size == 0) buffer += string(s);
-  else buffer += string(",") + string(s);
-  size++;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGfdmSocket::Append(long item)
-{
-  char s[25];
-
-  sprintf(s,"%12ld",item);
-
-  if (size == 0) buffer += string(s);
-  else buffer += string(",") + string(s);
-  size++;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGfdmSocket::Send(void)
-{
-  buffer += string("\n");
-  if ((send(sckt,buffer.c_str(),buffer.size(),0)) <= 0) {
-    perror("send");
-  } else {
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGfdmSocket::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: FGfdmSocket" << endl;
-    if (from == 1) cout << "Destroyed:    FGfdmSocket" << 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/FGfdmSocket.h b/src/FDM/JSBSim/FGfdmSocket.h
deleted file mode 100644 (file)
index 0c64541..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGfdmSocket.h
- Author:       Jon S. Berndt
- Date started: 11/08/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/08/99   JSB   Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGfdmSocket_H
-#define FGfdmSocket_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <stdio.h>
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  include STL_STRING
-#  include STL_IOSTREAM
-#  include STL_FSTREAM
-   SG_USING_STD(cout);
-   SG_USING_STD(endl);
-#else
-#  include <string>
-#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
-#    include <iostream.h>
-#    include <fstream.h>
-#  else
-#    include <iostream>
-#    include <fstream>
-     using std::cout;
-     using std::endl;
-#  endif
-#endif
-
-#include <sys/types.h>
-#include "FGJSBBase.h"
-
-#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
-  #include <winsock.h>
-#else
-  #include <sys/socket.h>
-  #include <netinet/in.h>
-  #include <netdb.h>
-  #include <errno.h>
-#endif
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_FDMSOCKET "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates a socket object.
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-using std::string;
-
-class FGfdmSocket : public FGJSBBase
-{
-public:
-  FGfdmSocket(string, int);
-  ~FGfdmSocket();
-  void Send(void);
-  void Append(const char*);
-  void Append(double);
-  void Append(long);
-  void Clear(void);
-  bool GetConnectStatus(void) {return connected;}
-
-private:
-  int sckt;
-  int size;
-  struct sockaddr_in scktName;
-  struct hostent *host;
-  string buffer;
-  bool connected;
-  void Debug(int from);
-};
-}
-#endif
index d7ffc2ad553b90bfc073435c67030be55e394f2a..a60060e8a1a4e4edee4277c7f4beebeee1dddd74 100644 (file)
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 
+#include "JSBSim.hxx"
 #include <FDM/JSBSim/FGFDMExec.h>
-#include <FDM/JSBSim/FGAircraft.h>
-#include <FDM/JSBSim/FGFCS.h>
-#include <FDM/JSBSim/FGPropagate.h>
+#include <FDM/JSBSim/FGJSBBase.h>
 #include <FDM/JSBSim/FGState.h>
-#include <FDM/JSBSim/FGAuxiliary.h>
-#include <FDM/JSBSim/FGInitialCondition.h>
-#include <FDM/JSBSim/FGTrim.h>
-#include <FDM/JSBSim/FGAtmosphere.h>
-#include <FDM/JSBSim/FGMassBalance.h>
-#include <FDM/JSBSim/FGAerodynamics.h>
-#include <FDM/JSBSim/FGLGear.h>
-#include <FDM/JSBSim/FGPropertyManager.h>
-#include <FDM/JSBSim/FGEngine.h>
-#include <FDM/JSBSim/FGPiston.h>
-#include <FDM/JSBSim/FGGroundCallback.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"
+#include <FDM/JSBSim/initialization/FGInitialCondition.h>
+#include <FDM/JSBSim/initialization/FGTrim.h>
+#include <FDM/JSBSim/models/FGModel.h>
+#include <FDM/JSBSim/models/FGAircraft.h>
+#include <FDM/JSBSim/models/FGFCS.h>
+#include <FDM/JSBSim/models/FGPropagate.h>
+#include <FDM/JSBSim/models/FGAuxiliary.h>
+#include <FDM/JSBSim/models/FGAtmosphere.h>
+#include <FDM/JSBSim/models/FGMassBalance.h>
+#include <FDM/JSBSim/models/FGAerodynamics.h>
+#include <FDM/JSBSim/models/FGLGear.h>
+#include <FDM/JSBSim/models/propulsion/FGEngine.h>
+#include <FDM/JSBSim/models/propulsion/FGPiston.h>
+#include <FDM/JSBSim/models/propulsion/FGTurbine.h>
+#include <FDM/JSBSim/models/propulsion/FGTurboProp.h>
+#include <FDM/JSBSim/models/propulsion/FGRocket.h>
+#include <FDM/JSBSim/models/propulsion/FGElectric.h>
+#include <FDM/JSBSim/models/propulsion/FGNozzle.h>
+#include <FDM/JSBSim/models/propulsion/FGPropeller.h>
+#include <FDM/JSBSim/models/propulsion/FGRotor.h>
+#include <FDM/JSBSim/models/propulsion/FGTank.h>
+#include <FDM/JSBSim/input_output/FGPropertyManager.h>
+#include <FDM/JSBSim/input_output/FGGroundCallback.h>
+
+using namespace JSBSim;
 
 static inline double
 FMAX (double a, double b)
@@ -142,10 +147,6 @@ FGJSBsim::FGJSBsim( double dt )
         }
     }
 
-    reset_on_crash = fgGetBool("/sim/reset-on-crash", false);
-    crashed = false;
-    fgSetBool("/sim/crashed", false);
-
     fdmex = new FGFDMExec( (FGPropertyManager*)globals->get_props() );
 
     // Register ground callback.
@@ -288,9 +289,6 @@ 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(
@@ -307,7 +305,6 @@ void FGJSBsim::init()
     } else {
       Atmosphere->UseInternal();
     }
-#endif
 
     fgic->SetVnorthFpsIC( wind_from_north->getDoubleValue() );
     fgic->SetVeastFpsIC( wind_from_east->getDoubleValue() );
@@ -339,9 +336,9 @@ void FGJSBsim::init()
     switch(fgic->GetSpeedSet()) {
     case setned:
         SG_LOG(SG_FLIGHT,SG_INFO, "  Vn,Ve,Vd= "
-               << Propagate->GetVel(eNorth) << ", "
-               << Propagate->GetVel(eEast) << ", "
-               << Propagate->GetVel(eDown) << " ft/s");
+               << Propagate->GetVel(FGJSBBase::eNorth) << ", "
+               << Propagate->GetVel(FGJSBBase::eEast) << ", "
+               << Propagate->GetVel(FGJSBBase::eDown) << " ft/s");
     break;
     case setuvw:
         SG_LOG(SG_FLIGHT,SG_INFO, "  U,V,W= "
@@ -363,11 +360,11 @@ void FGJSBsim::init()
     stall_warning->setDoubleValue(0);
 
     SG_LOG( SG_FLIGHT, SG_INFO, "  Bank Angle: "
-            << Propagate->GetEuler(ePhi)*RADTODEG << " deg" );
+            << Propagate->GetEuler(FGJSBBase::ePhi)*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Pitch Angle: "
-            << Propagate->GetEuler(eTht)*RADTODEG << " deg" );
+            << Propagate->GetEuler(FGJSBBase::eTht)*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  True Heading: "
-            << Propagate->GetEuler(ePsi)*RADTODEG << " deg" );
+            << Propagate->GetEuler(FGJSBBase::ePsi)*RADTODEG << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Latitude: "
             << Propagate->GetLocation().GetLatitudeDeg() << " deg" );
     SG_LOG( SG_FLIGHT, SG_INFO, "  Longitude: "
@@ -487,12 +484,6 @@ void FGJSBsim::update( double dt )
     // translate JSBsim back to FG structure so that the
     // autopilot (and the rest of the sim can use the updated values
     copy_from_JSBsim();
-
-    // crashed (altitude AGL < 0)
-    if (get_Altitude_AGL() < 0.0) {
-      crash_message = "Attempted to fly under ground.";
-      crash_handler();
-    }
 }
 
 /******************************************************************************/
@@ -534,6 +525,7 @@ bool FGJSBsim::copy_to_JSBsim()
       FCS->SetThrottleCmd(i, globals->get_controls()->get_throttle(i));
       FCS->SetMixtureCmd(i, globals->get_controls()->get_mixture(i));
       FCS->SetPropAdvanceCmd(i, globals->get_controls()->get_prop_advance(i));
+      FCS->SetFeatherCmd(i, globals->get_controls()->get_feather(i));
 
       switch (Propulsion->GetEngine(i)->GetType()) {
       case FGEngine::etPiston:
@@ -557,6 +549,17 @@ bool FGJSBsim::copy_to_JSBsim()
         FGRocket* eng = (FGRocket*)Propulsion->GetEngine(i);
         break;
         } // end FGRocket code block
+      case FGEngine::etTurboprop:
+        { // FGTurboProp code block
+        FGTurboProp* eng = (FGTurboProp*)Propulsion->GetEngine(i);
+        eng->SetReverse( globals->get_controls()->get_reverser(i) );
+        eng->SetCutoff( globals->get_controls()->get_cutoff(i) );
+        eng->SetIgnition( globals->get_controls()->get_ignition(i) );
+
+               eng->SetGeneratorPower( globals->get_controls()->get_generator_breaker(i) );
+               eng->SetCondition( globals->get_controls()->get_condition(i) );
+        break;
+        } // end FGTurboProp code block
       }
 
       { // FGEngine code block
@@ -636,18 +639,18 @@ bool FGJSBsim::copy_from_JSBsim()
 
     // Velocities
 
-    _set_Velocities_Local( Propagate->GetVel(eNorth),
-                           Propagate->GetVel(eEast),
-                           Propagate->GetVel(eDown) );
+    _set_Velocities_Local( Propagate->GetVel(FGJSBBase::eNorth),
+                           Propagate->GetVel(FGJSBBase::eEast),
+                           Propagate->GetVel(FGJSBBase::eDown) );
 
     _set_Velocities_Wind_Body( Propagate->GetUVW(1),
                                Propagate->GetUVW(2),
                                Propagate->GetUVW(3) );
 
     // Make the HUD work ...
-    _set_Velocities_Ground( Propagate->GetVel(eNorth),
-                            Propagate->GetVel(eEast),
-                            -Propagate->GetVel(eDown) );
+    _set_Velocities_Ground( Propagate->GetVel(FGJSBBase::eNorth),
+                            Propagate->GetVel(FGJSBBase::eEast),
+                            -Propagate->GetVel(FGJSBBase::eDown) );
 
     _set_V_rel_wind( Auxiliary->GetVt() );
 
@@ -657,13 +660,13 @@ bool FGJSBsim::copy_from_JSBsim()
 
     _set_V_ground_speed( Auxiliary->GetVground() );
 
-    _set_Omega_Body( Propagate->GetPQR(eP),
-                     Propagate->GetPQR(eQ),
-                     Propagate->GetPQR(eR) );
+    _set_Omega_Body( Propagate->GetPQR(FGJSBBase::eP),
+                     Propagate->GetPQR(FGJSBBase::eQ),
+                     Propagate->GetPQR(FGJSBBase::eR) );
 
-    _set_Euler_Rates( Auxiliary->GetEulerRates(ePhi),
-                      Auxiliary->GetEulerRates(eTht),
-                      Auxiliary->GetEulerRates(ePsi) );
+    _set_Euler_Rates( Auxiliary->GetEulerRates(FGJSBBase::ePhi),
+                      Auxiliary->GetEulerRates(FGJSBBase::eTht),
+                      Auxiliary->GetEulerRates(FGJSBBase::ePsi) );
 
     _set_Mach_number( Auxiliary->GetMach() );
 
@@ -674,7 +677,7 @@ bool FGJSBsim::copy_from_JSBsim()
 
     _set_Altitude_AGL( Propagate->GetDistanceAGL() );
     {
-      double loc_cart[3] = { l(eX), l(eY), l(eZ) };
+      double loc_cart[3] = { l(FGJSBBase::eX), l(FGJSBBase::eY), l(FGJSBBase::eZ) };
       double contact[3], d[3], sd, t;
       int id;
       is_valid_m(&t, d, &sd);
@@ -684,9 +687,9 @@ bool FGJSBsim::copy_from_JSBsim()
       _set_Runway_altitude( rwrad - get_Sea_level_radius() );
     }
 
-    _set_Euler_Angles( Propagate->GetEuler(ePhi),
-                       Propagate->GetEuler(eTht),
-                       Propagate->GetEuler(ePsi) );
+    _set_Euler_Angles( Propagate->GetEuler(FGJSBBase::ePhi),
+                       Propagate->GetEuler(FGJSBBase::eTht),
+                       Propagate->GetEuler(FGJSBBase::ePsi) );
 
     _set_Alpha( Auxiliary->Getalpha() );
     _set_Beta( Auxiliary->Getbeta() );
@@ -751,6 +754,28 @@ bool FGJSBsim::copy_from_JSBsim()
         globals->get_controls()->set_augmentation(i, eng->GetAugmentation() );
         } // end FGTurbine code block
         break;
+      case FGEngine::etTurboprop:
+        { // FGTurboProp code block
+        FGTurboProp* eng = (FGTurboProp*)Propulsion->GetEngine(i);
+        node->setDoubleValue("n1", eng->GetN1());
+        //node->setDoubleValue("n2", eng->GetN2());
+        node->setDoubleValue("itt_degf", 32 + eng->GetITT()*9/5);
+        node->setBoolValue("ignition", eng->GetIgnition());
+        node->setDoubleValue("nozzle-pos-norm", eng->GetNozzle());
+        node->setDoubleValue("inlet-pos-norm", eng->GetInlet());
+        node->setDoubleValue("oil-pressure-psi", eng->getOilPressure_psi());
+        node->setBoolValue("reversed", eng->GetReversed());
+        node->setBoolValue("cutoff", eng->GetCutoff());
+        node->setBoolValue("starting", eng->GetEngStarting());
+        node->setBoolValue("generator-power", eng->GetGeneratorPower());
+        node->setBoolValue("damaged", eng->GetCondition());
+        node->setBoolValue("ielu-intervent", eng->GetIeluIntervent());
+        node->setDoubleValue("oil-temperature-degf", eng->getOilTemp_degF());
+//        node->setBoolValue("onfire", eng->GetFire());
+        globals->get_controls()->set_reverser(i, eng->GetReversed() );
+        globals->get_controls()->set_cutoff(i, eng->GetCutoff() );
+        } // end FGTurboProp code block
+        break;
       case FGEngine::etElectric:
         { // FGElectric code block
         FGElectric* eng = (FGElectric*)Propulsion->GetEngine(i);
@@ -782,6 +807,7 @@ bool FGJSBsim::copy_from_JSBsim()
         tnode->setDoubleValue("rpm", thruster->GetRPM());
         tnode->setDoubleValue("pitch", prop->GetPitch());
         tnode->setDoubleValue("torque", prop->GetTorque());
+        tnode->setBoolValue("feathered", prop->GetFeather());
         } // end FGPropeller code block
         break;
       case FGThruster::ttRotor:
@@ -823,23 +849,32 @@ bool FGJSBsim::copy_from_JSBsim()
     speedbrake_pos_pct->setDoubleValue( FCS->GetDsbPos(ofNorm) );
     spoilers_pos_pct->setDoubleValue( FCS->GetDspPos(ofNorm) );
 
+    // force a sim reset if crashed (altitude AGL < 0)
+    if (get_Altitude_AGL() < 0.0) {
+         fgSetBool("/sim/crashed", true);
+         SGPropertyNode* node = fgGetNode("/sim/presets", true);
+         globals->get_commands()->execute("old-reinit-dialog", node);
+    }
+
     return true;
 }
 
 
 bool FGJSBsim::ToggleDataLogging(void)
 {
-    return fdmex->GetOutput()->Toggle();
+  // ToDo: handle this properly
+  fdmex->DisableOutput();
+  return false;
 }
 
 
 bool FGJSBsim::ToggleDataLogging(bool state)
 {
     if (state) {
-      fdmex->GetOutput()->Enable();
+      fdmex->EnableOutput();
       return true;
     } else {
-      fdmex->GetOutput()->Disable();
+      fdmex->DisableOutput();
       return false;
     }
 }
@@ -1098,17 +1133,3 @@ void FGJSBsim::update_ic(void)
    }
 }
 
-void FGJSBsim::crash_handler(void)
-{
-   if (crashed) return;  // we already crashed
-   crashed = true;
-   fgSetBool("/sim/crashed", true);
-   SG_LOG( SG_FLIGHT, SG_WARN, "  Crash: " << crash_message );
-   if (reset_on_crash) {
-     SGPropertyNode* node = fgGetNode("/sim/presets", true);
-     globals->get_commands()->execute("old-reinit-dialog", node);   
-   } else {
-     fgSetBool("/sim/freeze/master", true);
-     fgSetBool("/sim/freeze/clock", true);
-   }
-}
index 64f1dfcb1364b5ff226e2055972c2833939caf82..5bd13816b26b176962fc4220abe1863406141dd1 100644 (file)
@@ -72,7 +72,8 @@ class FGOutput;
 class FGInitialCondition;
 }
 
-using namespace JSBSim;
+// Adding it here will cause a namespace clash in FlightGear -EMH-
+// using namespace JSBSim;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DOCUMENTATION
@@ -205,24 +206,21 @@ public:
     void do_trim(void);
     void update_ic(void);
 
-    //** Handle a crash of the user aircraft. */
-    void crash_handler();
-
 private:
-    FGFDMExec *fdmex;
-    FGInitialCondition *fgic;
+    JSBSim::FGFDMExec *fdmex;
+    JSBSim::FGInitialCondition *fgic;
     bool needTrim;
 
-    FGState*        State;
-    FGAtmosphere*   Atmosphere;
-    FGFCS*          FCS;
-    FGPropulsion*   Propulsion;
-    FGMassBalance*  MassBalance;
-    FGAircraft*     Aircraft;
-    FGPropagate*    Propagate;
-    FGAuxiliary*    Auxiliary;
-    FGAerodynamics* Aerodynamics;
-    FGGroundReactions *GroundReactions;
+    JSBSim::FGState*        State;
+    JSBSim::FGAtmosphere*   Atmosphere;
+    JSBSim::FGFCS*          FCS;
+    JSBSim::FGPropulsion*   Propulsion;
+    JSBSim::FGMassBalance*  MassBalance;
+    JSBSim::FGAircraft*     Aircraft;
+    JSBSim::FGPropagate*    Propagate;
+    JSBSim::FGAuxiliary*    Auxiliary;
+    JSBSim::FGAerodynamics* Aerodynamics;
+    JSBSim::FGGroundReactions *GroundReactions;
 
     int runcount;
     double trim_elev;
@@ -266,10 +264,6 @@ private:
     void init_gear(void);
     void update_gear(void);
 
-    bool reset_on_crash;
-    bool crashed;
-    string crash_message;
-
 };
 
 
index fd3001eb78d771279d59cc189c70fa7e0d67c1e2..c2d2b93c70e2585b00c649ef4127645375ed63fe 100644 (file)
@@ -1,58 +1,9 @@
-SUBDIRS = filtersjb
-
-EXTRA_DIST = Makefile.solo
+SUBDIRS = initialization models input_output math
 
 noinst_LIBRARIES = libJSBSim.a
 
-libJSBSim_a_SOURCES = \
-       FGAerodynamics.cpp FGAerodynamics.h \
-       FGAircraft.cpp FGAircraft.h \
-       FGAtmosphere.cpp FGAtmosphere.h \
-       FGAuxiliary.cpp FGAuxiliary.h \
-       FGCoefficient.cpp FGCoefficient.h \
-        FGColumnVector3.cpp FGColumnVector3.h \
-       FGConfigFile.cpp FGConfigFile.h \
-       FGFCS.cpp FGFCS.h \
-       FGFDMExec.cpp FGFDMExec.h \
-       FGFactorGroup.cpp FGFactorGroup.h \
-       FGForce.cpp FGForce.h \
-        FGGroundReactions.cpp FGGroundReactions.h \
-        FGInertial.cpp FGInertial.h \
-       FGInitialCondition.cpp FGInitialCondition.h \
-        FGJSBBase.cpp FGJSBBase.h \
-       FGLGear.cpp FGLGear.h \
-        FGMassBalance.cpp FGMassBalance.h \
-        FGMatrix33.cpp FGMatrix33.h \
-       FGModel.cpp FGModel.h \
-       FGNozzle.cpp FGNozzle.h \
-       FGOutput.cpp FGOutput.h \
-        FGPiston.cpp FGPiston.h \
-        FGPropeller.cpp FGPropeller.h \
-        FGPropulsion.cpp FGPropulsion.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 \
-       FGTrim.cpp FGTrim.h \
-       FGTrimAxis.cpp FGTrimAxis.h \
-       FGTurbine.cpp FGTurbine.h \
-       FGEngine.cpp FGEngine.h \
-       FGTank.cpp FGTank.h \
-       FGfdmSocket.cpp FGfdmSocket.h \
-       FGTurbine.cpp FGTurbine.h \
-       FGPropertyManager.cpp FGPropertyManager.h  \
-       FGPropagate.cpp FGPropagate.h \
-       FGLocation.cpp FGLocation.h \
-       FGQuaternion.cpp FGQuaternion.h \
-       FGElectric.cpp FGElectric.h \
-       FGGroundCallback.cpp FGGroundCallback.h \
-       JSBSim.cxx JSBSim.hxx
-
-
-# noinst_PROGRAMS = testJSBsim
+libJSBSim_a_SOURCES =  FGFDMExec.cpp FGJSBBase.cpp FGState.cpp JSBSim.cxx
 
-AM_CXXFLAGS = -DFGFS
+noinst_HEADERS = FGFDMExec.h FGJSBBase.h FGState.h JSBSim.hxx
 
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
+INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/FDM/JSBSim
diff --git a/src/FDM/JSBSim/Makefile.solo b/src/FDM/JSBSim/Makefile.solo
deleted file mode 100644 (file)
index b1a1045..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-CC = g++
-INCLUDES = -I.
-LINKDIR= -Lfiltersjb/
-JSBSim_objects = FGAircraft.o FGAtmosphere.o FGCoefficient.o FGFCS.o FGFDMExec.o\
-FGModel.o FGOutput.o FGPosition.o FGRotation.o FGState.o FGTranslation.o\
-FGUtility.o FGTank.o FGAuxiliary.o FGfdmSocket.o FGTrim.o FGTrimAxis.o\
-FGConfigFile.o FGInitialCondition.o FGLGear.o FGMatrix.o FGPropulsion.o FGRocket.o\
-FGTurboShaft.o FGTurboJet.o FGTurboProp.o FGPiston.o FGForce.o FGThruster.o FGEngine.o\
-FGTable.o FGPropeller.o FGNozzle.o FGAerodynamics.o FGMassBalance.o FGInertial.o\
-FGFactorGroup.o
-
-JSBSim : $(JSBSim_objects) JSBSim.o libFCSComponents.a
-       $(CC) $(INCLUDES) $(CCOPTS) $(LINKDIR) $(JSBSim_objects) JSBSim.o -oJSBSim -lm -lFCSComponents
-
-libFCSComponents.a:
-       cd filtersjb; make -fMakefile.solo; cd ..
-
-FGAerodynamics.o: FGAerodynamics.cpp FGAerodynamics.h FGModel.h \
- FGDefs.h FGConfigFile.h FGState.h FGInitialCondition.h FGFDMExec.h \
- FGAtmosphere.h FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h \
- filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
- FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
- FGCoefficient.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGAerodynamics.cpp
-
-FGAircraft.o: FGAircraft.cpp FGAircraft.h FGModel.h FGDefs.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGInitialCondition.h \
- FGFDMExec.h FGAtmosphere.h FGMatrix.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGConfigFile.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
- FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGNozzle.h FGInertial.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGAircraft.cpp
-
-FGAtmosphere.o: FGAtmosphere.cpp FGAtmosphere.h FGModel.h FGDefs.h \
- FGMatrix.h FGState.h FGInitialCondition.h FGFDMExec.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
- FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
- FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
- FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGAtmosphere.cpp
-
-FGAuxiliary.o: FGAuxiliary.cpp FGAuxiliary.h FGModel.h FGDefs.h \
- FGMatrix.h FGTranslation.h FGRotation.h FGAtmosphere.h FGState.h \
- FGInitialCondition.h FGFDMExec.h FGFCS.h filtersjb/FGFCSComponent.h \
- filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h \
- FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h FGPosition.h \
- FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
- FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGAuxiliary.cpp
-
-FGCoefficient.o: FGCoefficient.cpp FGCoefficient.h FGConfigFile.h \
- FGDefs.h FGTable.h FGState.h FGInitialCondition.h FGFDMExec.h \
- FGModel.h FGAtmosphere.h FGMatrix.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h \
- FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h FGOutput.h \
- FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h \
- FGTank.h FGPropeller.h FGThruster.h FGForce.h FGNozzle.h \
- FGMassBalance.h FGAerodynamics.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGCoefficient.cpp
-
-FGColumnVector3.o: FGColumnVector3.cpp FGColumnVector3.h FGMatrix.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGColumnVector3.cpp
-
-FGConfigFile.o: FGConfigFile.cpp FGConfigFile.h FGDefs.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGConfigFile.cpp
-
-FGEngine.o: FGEngine.cpp FGEngine.h FGState.h FGDefs.h \
- FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGEngine.cpp
-
-FGFCS.o: FGFCS.cpp FGDefs.h FGFCS.h filtersjb/FGFCSComponent.h \
- filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGModel.h FGLGear.h \
- FGConfigFile.h FGMatrix.h FGFDMExec.h FGInitialCondition.h \
- FGAtmosphere.h FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h \
- FGState.h FGTranslation.h FGRotation.h FGPosition.h FGAerodynamics.h \
- FGMassBalance.h FGCoefficient.h FGTable.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h \
- FGNozzle.h filtersjb/FGFilter.h filtersjb/../FGConfigFile.h \
- filtersjb/FGDeadBand.h filtersjb/FGGain.h filtersjb/../FGTable.h \
- filtersjb/FGGradient.h filtersjb/FGSwitch.h filtersjb/FGSummer.h \
- filtersjb/FGFlaps.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGFCS.cpp
-
-FGFDMExec.o: FGFDMExec.cpp FGFDMExec.h FGModel.h FGDefs.h \
- FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGState.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
- FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
- FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
- FGFactorGroup.h FGInertial.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGFDMExec.cpp
-
-FGFactorGroup.o: FGFactorGroup.cpp FGCoefficient.h FGConfigFile.h \
- FGDefs.h FGTable.h FGFactorGroup.h FGAerodynamics.h FGModel.h \
- FGState.h FGInitialCondition.h FGFDMExec.h FGAtmosphere.h FGMatrix.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGAircraft.h FGPropulsion.h FGRocket.h \
- FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
- FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h \
- FGNozzle.h FGMassBalance.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGFactorGroup.cpp
-
-FGForce.o: FGForce.cpp FGFDMExec.h FGModel.h FGDefs.h \
- FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGConfigFile.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
- FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGNozzle.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGForce.cpp
-
-FGGroundReactions.o: FGGroundReactions.cpp FGGroundReactions.h \
- FGModel.h FGDefs.h FGConfigFile.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGGroundReactions.cpp
-
-FGInertial.o: FGInertial.cpp FGInertial.h FGModel.h FGDefs.h \
- FGConfigFile.h FGMatrix.h FGPosition.h FGMassBalance.h FGPropulsion.h \
- FGRocket.h FGEngine.h FGState.h FGInitialCondition.h FGFDMExec.h \
- FGAtmosphere.h FGFCS.h filtersjb/FGFCSComponent.h \
- filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGAircraft.h \
- FGRotation.h FGTranslation.h FGAerodynamics.h FGCoefficient.h \
- FGTable.h FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h \
- FGPiston.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h \
- FGPropeller.h FGThruster.h FGForce.h FGNozzle.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGInertial.cpp
-
-FGInitialCondition.o: FGInitialCondition.cpp FGInitialCondition.h \
- FGFDMExec.h FGModel.h FGDefs.h FGAtmosphere.h FGMatrix.h FGState.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
- FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGInitialCondition.cpp
-
-FGLGear.o: FGLGear.cpp FGLGear.h FGConfigFile.h FGDefs.h FGMatrix.h \
- FGFDMExec.h FGModel.h FGInitialCondition.h FGAtmosphere.h \
- FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGTranslation.h FGRotation.h FGPosition.h FGAerodynamics.h \
- FGMassBalance.h FGCoefficient.h FGTable.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h \
- FGNozzle.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGLGear.cpp
-
-FGMassBalance.o: FGMassBalance.cpp FGMassBalance.h FGModel.h FGDefs.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGState.h FGInitialCondition.h \
- FGFDMExec.h FGAtmosphere.h FGMatrix.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGConfigFile.h FGAircraft.h FGPosition.h FGRotation.h \
- FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
- FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGNozzle.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGMassBalance.cpp
-
-FGMatrix.o: FGMatrix.cpp FGMatrix.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGMatrix.cpp
-
-FGModel.o: FGModel.cpp FGModel.h FGDefs.h FGState.h \
- FGInitialCondition.h FGFDMExec.h FGAtmosphere.h FGMatrix.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
- FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
- FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
- FGFactorGroup.h FGInertial.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGModel.cpp
-
-FGNozzle.o: FGNozzle.cpp FGNozzle.h FGThruster.h FGForce.h FGFDMExec.h \
- FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h FGMatrix.h \
- FGConfigFile.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGNozzle.cpp
-
-FGOutput.o: FGOutput.cpp FGOutput.h FGModel.h FGDefs.h FGfdmSocket.h \
- FGState.h FGInitialCondition.h FGFDMExec.h FGAtmosphere.h FGMatrix.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
- FGPosition.h FGAuxiliary.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
- FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGOutput.cpp
-
-FGPiston.o: FGPiston.cpp FGDefs.h FGPiston.h FGEngine.h FGState.h \
- FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h \
- FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGPiston.cpp
-
-FGPosition.o: FGPosition.cpp FGPosition.h FGModel.h FGDefs.h \
- FGMatrix.h FGAtmosphere.h FGState.h FGInitialCondition.h FGFDMExec.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
- FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
- FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
- FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
- FGCoefficient.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGPosition.cpp
-
-FGPropeller.o: FGPropeller.cpp FGPropeller.h FGThruster.h FGForce.h \
- FGFDMExec.h FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h \
- FGMatrix.h FGConfigFile.h FGTable.h FGTranslation.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGPropeller.cpp
-
-FGPropulsion.o: FGPropulsion.cpp FGPropulsion.h FGModel.h FGDefs.h \
- FGRocket.h FGEngine.h FGState.h FGInitialCondition.h FGFDMExec.h \
- FGAtmosphere.h FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h \
- filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h \
- FGAircraft.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGTranslation.h FGAerodynamics.h FGCoefficient.h FGTable.h \
- FGFactorGroup.h FGOutput.h FGfdmSocket.h FGAuxiliary.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGNozzle.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGPropulsion.cpp
-
-FGRocket.o: FGRocket.cpp FGDefs.h FGRocket.h FGEngine.h FGState.h \
- FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGPiston.h FGTurboShaft.h FGTurboJet.h FGTurboProp.h \
- FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGRocket.cpp
-
-FGRotation.o: FGRotation.cpp FGRotation.h FGModel.h FGDefs.h \
- FGMatrix.h FGAtmosphere.h FGState.h FGInitialCondition.h FGFDMExec.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGPosition.h \
- FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
- FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
- FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
- FGCoefficient.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGRotation.cpp
-
-FGRotor.o: FGRotor.cpp FGRotor.h FGThruster.h FGForce.h FGFDMExec.h \
- FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h FGMatrix.h \
- FGConfigFile.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGRotor.cpp
-
-FGState.o: FGState.cpp FGState.h FGDefs.h FGInitialCondition.h \
- FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h FGFCS.h \
- filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h filtersjb/../FGFCS.h \
- FGLGear.h FGConfigFile.h FGAircraft.h FGPropulsion.h FGRocket.h \
- FGEngine.h FGTranslation.h FGRotation.h FGPosition.h FGAuxiliary.h \
- FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
- FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGState.cpp
-
-FGTable.o: FGTable.cpp FGTable.h FGConfigFile.h FGDefs.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTable.cpp
-
-FGTank.o: FGTank.cpp FGDefs.h FGTank.h FGConfigFile.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTank.cpp
-
-FGThruster.o: FGThruster.cpp FGThruster.h FGForce.h FGFDMExec.h \
- FGModel.h FGDefs.h FGInitialCondition.h FGAtmosphere.h FGMatrix.h \
- FGConfigFile.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGThruster.cpp
-
-FGTranslation.o: FGTranslation.cpp FGTranslation.h FGModel.h FGDefs.h \
- FGMatrix.h FGRotation.h FGAtmosphere.h FGState.h FGInitialCondition.h \
- FGFDMExec.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGPosition.h FGAuxiliary.h \
- FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGNozzle.h FGMassBalance.h FGAerodynamics.h FGCoefficient.h \
- FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTranslation.cpp
-
-FGTrim.o: FGTrim.cpp FGFDMExec.h FGModel.h FGDefs.h \
- FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGTrim.h FGRotation.h \
- FGState.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGPosition.h \
- FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
- FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
- FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
- FGCoefficient.h FGFactorGroup.h FGTrimAxis.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTrim.cpp
-
-FGTrimAxis.o: FGTrimAxis.cpp FGFDMExec.h FGModel.h FGDefs.h \
- FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGTrimAxis.h \
- FGRotation.h FGState.h FGFCS.h filtersjb/FGFCSComponent.h \
- filtersjb/../FGDefs.h filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h \
- FGAircraft.h FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h \
- FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTrimAxis.cpp
-
-FGTurboJet.o: FGTurboJet.cpp FGTurboJet.h FGEngine.h FGState.h \
- FGDefs.h FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h \
- FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGPiston.h FGTurboShaft.h FGTurboProp.h \
- FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTurboJet.cpp
-
-FGTurboProp.o: FGTurboProp.cpp FGTurboProp.h FGEngine.h FGState.h \
- FGDefs.h FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h \
- FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGPiston.h FGTurboShaft.h FGTurboJet.h \
- FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTurboProp.cpp
-
-FGTurboShaft.o: FGTurboShaft.cpp FGTurboShaft.h FGEngine.h FGState.h \
- FGDefs.h FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h \
- FGMatrix.h FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGPiston.h FGTurboJet.h FGTurboProp.h \
- FGTank.h FGPropeller.h FGThruster.h FGForce.h FGTable.h \
- FGTranslation.h FGNozzle.h FGPosition.h FGRotation.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h FGOutput.h \
- FGfdmSocket.h FGAuxiliary.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGTurboShaft.cpp
-
-FGUtility.o: FGUtility.cpp FGUtility.h FGState.h FGDefs.h \
- FGInitialCondition.h FGFDMExec.h FGModel.h FGAtmosphere.h FGMatrix.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGRotation.h \
- FGPosition.h FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h \
- FGTurboShaft.h FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h \
- FGThruster.h FGForce.h FGTable.h FGNozzle.h FGMassBalance.h \
- FGAerodynamics.h FGCoefficient.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGUtility.cpp
-
-FGfdmSocket.o: FGfdmSocket.cpp FGfdmSocket.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c FGfdmSocket.cpp
-
-JSBSim.o: JSBSim.cpp FGFDMExec.h FGModel.h FGDefs.h \
- FGInitialCondition.h FGAtmosphere.h FGMatrix.h FGRotation.h FGState.h \
- FGFCS.h filtersjb/FGFCSComponent.h filtersjb/../FGDefs.h \
- filtersjb/../FGFCS.h FGLGear.h FGConfigFile.h FGAircraft.h \
- FGPropulsion.h FGRocket.h FGEngine.h FGTranslation.h FGPosition.h \
- FGAuxiliary.h FGOutput.h FGfdmSocket.h FGPiston.h FGTurboShaft.h \
- FGTurboJet.h FGTurboProp.h FGTank.h FGPropeller.h FGThruster.h \
- FGForce.h FGTable.h FGNozzle.h FGMassBalance.h FGAerodynamics.h \
- FGCoefficient.h FGFactorGroup.h
-       $(CC) $(INCLUDES) $(CCOPTS) -c JSBSim.cpp
-
-
-x15trim.o:x15trim.cpp
-       $(CC) $(INCLUDES) $(CCOPTS) -c x15trim.cpp
-
-x15trim:$(JSBSim_objects) x15trim.o libFCSComponents.a
-       $(CC) $(INCLUDES) $(CCOPTS) $(LINKDIR) $(JSBSim_objects) x15trim.o -ox15trim -lm -lFCSComponents
-
-clean:
-       -mv *.*~ backup
-       -rm *.o
-
-all:
-       touch *.cpp
-       cd filtersjb; make all -fMakefile.solo; cd ..
-       make JSBSim -fMakefile.solo
-
-debug:
-       touch *.cpp
-       touch filtersjb/*.cpp
-       cd filtersjb; make debug CCOPTS=-g -fMakefile.solo; cd ..
-       make JSBSim CCOPTS=-g -fMakefile.solo
diff --git a/src/FDM/JSBSim/README b/src/FDM/JSBSim/README
deleted file mode 100644 (file)
index 2ad5ae7..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-Contents\r
---------\r
-\r
-1) Introduction\r
-2) Building with autoconf/automake\r
-3) Contact\r
-\r
-\r
-1) Introduction\r
----------------\r
-\r
-JSBSim is a multi-platform, general purpose object-oriented Flight\r
-Dynamics Model (FDM) written in C++. Jon Berndt and Tony Peden began\r
-about mid-1998 writing JSBSim. As of this writing it is the default\r
-FDM for FlightGear. JSBSim can also be run in a standalone batch mode\r
-for testing and study. More information on JSBSim can be found at the\r
-JSBSim home page here:\r
-\r
-http://jsbsim.sourceforge.net\r
-\r
-The standalone version of JSBSim can be easily built from the command\r
-line of a unix or unix-like (CygWin/Linux/Unix/IRIX, etc.) system like\r
-this:\r
-\r
-make -fMakefile.solo\r
-\r
-If you are on an IRIX machine you can use the Makefile.irix makefile.\r
-Directions are also provided below for using traditional auto* utilities\r
-also provided with JSBSim.\r
-\r
-\r
-2) Building with autoconf/automake\r
-----------------------------------\r
-\r
-Unpack the distribution tarball (if needed - CVS users will have\r
-downloaded the code directly) using your preferred method, and change\r
-to the working directory. For example :\r
-\r
-$ tar xvfz JSBSim-0.1.2.tar.gz\r
-$ cd JSBSim-0.1.2\r
-\r
-NOTE for CVS users: If you are using JSBSim from a CVS checkout, or\r
-snapshot, you will need to create the initial configure script. The\r
-commands to do this have been included in the 'autogen.sh' script, so\r
-just :\r
-\r
-$ ./autogen.sh\r
-\r
-If you wish to customise your version of JSBSim, use the following to\r
-determine any build-time options you may be interested in.\r
-\r
-$ ./configure --help\r
-\r
-Then :\r
-\r
-$ ./configure\r
-\r
-This will check your system platform, compiler and other local\r
-configuration variables needed to build JSBSim, and generates the\r
-necessary Makefiles. Next :\r
-\r
-$ make\r
-\r
-Will compile the various classes, and link the library. Finally :\r
-\r
-$ make install\r
-\r
-Unless specified otherwise (with --prefix configure option), this will\r
-install 'JSBSim.a' into '/usr/local/lib'.\r
-\r
-\r
-3) Contact\r
-----------\r
-\r
-For more information on JSBSim contact Jon Berndt at jsbsim@hal-pc.org.\r
-\r
diff --git a/src/FDM/JSBSim/filtersjb/FGCondition.cpp b/src/FDM/JSBSim/filtersjb/FGCondition.cpp
deleted file mode 100644 (file)
index e3c5271..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGCondition.cpp
- Author:       Jon S. Berndt
- Date started: 1/2/2003
-
- -------------- Copyright (C) 2003 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGCondition.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_CONDITION;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-string FGCondition::indent = "        ";
-
-
-FGCondition::FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManager) :
-  PropertyManager(PropertyManager)
-{
-  mComparison["EQ"] = eEQ;
-  mComparison["NE"] = eNE;
-  mComparison["GT"] = eGT;
-  mComparison["GE"] = eGE;
-  mComparison["LT"] = eLT;
-  mComparison["LE"] = eLE;
-  mComparison["=="] = eEQ;
-  mComparison["!="] = eNE;
-  mComparison[">"]  = eGT;
-  mComparison[">="] = eGE;
-  mComparison["<"]  = eLT;
-  mComparison["<="] = eLE;
-
-  TestParam1  = TestParam2 = 0L;
-  TestValue   = 0.0;
-  Comparison  = ecUndef;
-  Logic       = elUndef;
-  conditions.clear();
-
-  if (AC_cfg->GetValue("CONDITION_GROUP").empty()) {  // define a condition
-
-    *AC_cfg >> property1 >> conditional >> property2;
-    TestParam1 = PropertyManager->GetNode(property1, true);
-    Comparison = mComparison[conditional];
-
-    if (property2.find_first_not_of("-.0123456789eE") == string::npos) {
-      TestValue = atof(property2.c_str());
-    } else {
-      TestParam2 = PropertyManager->GetNode(property2, true);
-    }
-
-    isGroup = false;
-
-  } else { // define a condition group
-
-    if (AC_cfg->GetValue("LOGIC") == "OR")       Logic = eOR;
-    else if (AC_cfg->GetValue("LOGIC") == "AND") Logic = eAND;
-
-    AC_cfg->GetNextConfigLine();
-    while (AC_cfg->GetValue() != string("/CONDITION_GROUP")) {
-      conditions.push_back(FGCondition(AC_cfg, PropertyManager));
-    }
-    isGroup = true;
-    AC_cfg->GetNextConfigLine();
-  }
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGCondition::~FGCondition(void)
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGCondition::Evaluate(void )
-{
-  vector <FGCondition>::iterator iConditions;
-  bool pass = false;
-  double compareValue;
-
-  if (Logic == eAND) {
-
-    iConditions = conditions.begin();
-    pass = true;
-    while (iConditions < conditions.end()) {
-      if (!iConditions->Evaluate()) pass = false;
-      *iConditions++;
-    }
-
-  } else if (Logic == eOR) {
-
-    pass = false;
-    while (iConditions < conditions.end()) {
-      if (iConditions->Evaluate()) pass = true;
-      *iConditions++;
-    }
-
-  } else {
-
-    if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue();
-    else compareValue = TestValue;
-
-    switch (Comparison) {
-    case ecUndef:
-      cerr << "Undefined comparison operator." << endl;
-      break;
-    case eEQ:
-      pass = TestParam1->getDoubleValue() == compareValue;
-      break;
-    case eNE:
-      pass = TestParam1->getDoubleValue() != compareValue;
-      break;
-    case eGT:
-      pass = TestParam1->getDoubleValue() > compareValue;
-      break;
-    case eGE:
-      pass = TestParam1->getDoubleValue() >= compareValue;
-      break;
-    case eLT:
-      pass = TestParam1->getDoubleValue() < compareValue;
-      break;
-    case eLE:
-      pass = TestParam1->getDoubleValue() <= compareValue;
-      break;
-    default:
-     cerr << "Unknown comparison operator." << endl;
-    }
-  }
-
-  return pass;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGCondition::PrintCondition(void )
-{
-  vector <FGCondition>::iterator iConditions;
-  string scratch;
-
-  if (isGroup) {
-    switch(Logic) {
-    case (elUndef):
-      scratch = " UNSET";
-      cerr << "unset logic for test condition" << endl;
-      break;
-    case (eAND):
-      scratch = " if all of the following are true";
-      break;
-    case (eOR):
-      scratch = " if any of the following are true:";
-      break;
-    default:
-      scratch = " UNKNOWN";
-      cerr << "Unknown logic for test condition" << endl;
-    }
-
-    iConditions = conditions.begin();
-    cout << scratch << endl;
-    while (iConditions < conditions.end()) {
-      iConditions->PrintCondition();
-      *iConditions++;
-    }
-  } else {
-    if (TestParam2 != 0L)
-      cout << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName();
-    else
-      cout << TestParam1->GetName() << " " << conditional << " " << TestValue;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGCondition::convert(void)
-{
-  if (conditions.empty())
-    cout << "                " << property1 << " " << conditional << " " << property2 << endl;
-  else
-    for (int i; i<conditions.size(); i++) conditions[i].convert();
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGCondition::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: FGCondition" << endl;
-    if (from == 1) cout << "Destroyed:    FGCondition" << 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;
-    }
-  }
-}
-
-} //namespace JSBSim
-
diff --git a/src/FDM/JSBSim/filtersjb/FGCondition.h b/src/FDM/JSBSim/filtersjb/FGCondition.h
deleted file mode 100644 (file)
index 0f2ba21..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGCondition.h
- Author:       Jon S. Berndt
- Date started: 1/02/2003
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGCONDITION_H
-#define FGCONDITION_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "../FGConfigFile.h"
-#include <map>
-#include "../FGPropertyManager.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_CONDITION "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates a condition, which is used in parts of JSBSim including switches
-*/
-   
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGCondition : public FGJSBBase
-{
-public:
-  FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManager);
-  ~FGCondition(void);
-
-  bool Evaluate(void);
-  void PrintCondition(void);
-  void convert(void);
-
-private:
-  FGConfigFile* AC_cfg;
-
-  enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE};
-  enum eLogic {elUndef=0, eAND, eOR};
-  map <string, eComparison> mComparison;
-  eLogic Logic;
-
-  FGPropertyManager *TestParam1, *TestParam2, *PropertyManager;
-  double TestValue;
-  eComparison Comparison;
-  bool isGroup;
-  string conditional;
-  string property1, property2;
-
-  static string indent;
-
-  vector <FGCondition> conditions;
-
-  void Debug(int from);
-};
-}
-#endif
-
diff --git a/src/FDM/JSBSim/filtersjb/FGDeadBand.cpp b/src/FDM/JSBSim/filtersjb/FGDeadBand.cpp
deleted file mode 100644 (file)
index 0158ecd..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGDeadBand.cpp
- Author:       Jon S. Berndt
- Date started: 11/1999
- ------------- Copyright (C) 2000 -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGDeadBand.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_DEADBAND;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGDeadBand::FGDeadBand(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
-                                                           AC_cfg(AC_cfg)
-{
-  Type = AC_cfg->GetValue("TYPE");
-  Name = AC_cfg->GetValue("NAME");
-  AC_cfg->GetNextConfigLine();
-  string token;
-
-  clipmax = clipmin = 0.0;
-  clip = false;
-  gain = 1.0;
-  width = 0.0;
-
-  while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
-    *AC_cfg >> token;
-    if (token == "INPUT") {
-      if (InputNodes.size() > 0) {
-        cerr << "Deadband can only accept one input" << endl;
-      } else  {
-        *AC_cfg >> token;
-        InputNodes.push_back(resolveSymbol(token));
-      }  
-    } else if (token == "WIDTH") {
-      *AC_cfg >> width;
-    } else if (token == "CLIPTO") {
-      *AC_cfg >> clipmin >> clipmax;
-      if (clipmax > clipmin) clip = true;
-    } else if (token == "GAIN") {
-      *AC_cfg >> gain;
-    } else if (token == "OUTPUT") {
-      *AC_cfg >> token;
-      OutputNode = PropertyManager->GetNode(token);
-    }
-  }
-  FGFCSComponent::bind();
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGDeadBand::~FGDeadBand()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGDeadBand::Run(void )
-{
-  FGFCSComponent::Run(); // call the base class for initialization of Input
-
-  Input = InputNodes[0]->getDoubleValue();
-
-  if (Input < -width/2.0) {
-    Output = (Input + width/2.0)*gain;
-  } else if (Input > width/2.0) {
-    Output = (Input - width/2.0)*gain;
-  } else {
-    Output = 0.0;
-  }
-
-  if (clip) {
-    if (Output > clipmax)      Output = clipmax;
-    else if (Output < clipmin) Output = clipmin;
-  }
-
-  if (IsOutput) SetOutput();
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGDeadBand::convert(void)
-{
-  cout << endl;
-  cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
-
-  cout << "            <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
-
-  if (gain != 1.0)
-    cout << "            <gain>" << gain << "</gain>" << endl;
-
-  cout << "                <width>" << width << "</width>" << endl;
-
-  if (clip) {
-    cout << "            <clip>" << endl;
-    cout << "                <min>" << clipmin << "</min>" << endl;
-    cout << "                <max>" << clipmax << "</max>" << endl;
-    cout << "            </clip>" << endl;
-  }
-
-  if (IsOutput)
-    cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
-
-  cout << "        </component>" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGDeadBand::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
-      cout << "      DEADBAND WIDTH: " << width << endl;
-      cout << "      GAIN: " << gain << endl;
-      if (clip) cout << "      CLIPTO: " << clipmin 
-                                  << ", " << clipmax << endl;
-      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGDeadBand" << endl;
-    if (from == 1) cout << "Destroyed:    FGDeadBand" << 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/filtersjb/FGDeadBand.h b/src/FDM/JSBSim/filtersjb/FGDeadBand.h
deleted file mode 100644 (file)
index c89a6c9..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGDeadBand.h
- Author:       
- Date started: 
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGDEADBAND_H
-#define FGDEADBAND_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGFCSComponent.h"
-#include "../FGConfigFile.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_DEADBAND "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-class FGFCS;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models a deadband object.
-    Here is the format of the deadband control specification:
-    <pre>
-    \<COMPONENT NAME="Deadbeat1" TYPE="DEADBAND">
-       INPUT {input}
-       WIDTH {deadband width}
-       MIN {minimum value}
-       MAX {maximum value}
-       [GAIN {optional deadband gain}]
-       [OUTPUT {optional output parameter to set}]
-    \</COMPONENT>
-    </pre>
-    The WIDTH value is the total deadband region within which an input will
-    produce no output. For example, say that the WIDTH value is 2.0.  If the
-    input is between -1.0 and +1.0, the output will be zero.
-    @author Jon S. Berndt
-    @version $Id$
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGDeadBand  : public FGFCSComponent         
-{
-public:
-  FGDeadBand(FGFCS* fcs, FGConfigFile* AC_cfg);
-  ~FGDeadBand();
-
-  bool Run(void);
-  void convert(void);
-
-private:
-  FGConfigFile* AC_cfg;
-  double width;
-  double clipmax, clipmin;
-  bool clip;
-  double gain;
-  
-  void Debug(int from);
-};
-}
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-#endif
diff --git a/src/FDM/JSBSim/filtersjb/FGFCSComponent.cpp b/src/FDM/JSBSim/filtersjb/FGFCSComponent.cpp
deleted file mode 100644 (file)
index 4833a64..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGFCSComponent.cpp
- Author:       Jon S. Berndt
- Date started: 11/1999
- ------------- Copyright (C) 2000 -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGFCSComponent.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_FCSCOMPONENT;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGFCSComponent::FGFCSComponent(FGFCS* _fcs) : fcs(_fcs)
-{
-  Type       = "";
-  Input      = 0.0;
-  Output     = 0.0;
-  OutputNode = 0;
-  IsOutput   = false;
-  PropertyManager=fcs->GetPropertyManager();
-  treenode   = 0;
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGFCSComponent::~FGFCSComponent()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFCSComponent::SetOutput(void)
-{
-  OutputNode->setDoubleValue(Output);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGFCSComponent::Run(void)
-{
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPropertyManager* FGFCSComponent::resolveSymbol(string token)
-{
-  string prop;
-  FGPropertyManager* tmp = PropertyManager->GetNode(token,false);
-  if (!tmp) {
-    if (token.find("/") == token.npos) prop = "model/" + token;
-    //cerr << "Creating new property " << prop << endl;
-    tmp = PropertyManager->GetNode(token,true);
-  }
-  return tmp;  
-}              
-      
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFCSComponent::bind(void)
-{
-  string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
-  FGPropertyManager *tmpn;
-  PropertyManager->Tie( tmp,this, &FGFCSComponent::GetOutput);
-  tmp = "fcs/components/" + PropertyManager->mkPropertyName(Name, true);
-  treenode = PropertyManager->GetNode( tmp, true );
-  for(unsigned i=0;i<InputNodes.size();i++) {
-    tmpn=treenode->GetNode( "input-property",(int)i,true );
-    tmpn->setStringValue( InputNodes[i]->GetName().c_str() );
-  }  
-  if(OutputNode) treenode->SetString("output-property",OutputNode->GetName());
-  treenode->Tie("output-value",this,&FGFCSComponent::GetOutput);
-  treenode->SetString("type",Type);
-}  
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGFCSComponent::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: FGFCSComponent" << endl;
-    if (from == 1) cout << "Destroyed:    FGFCSComponent" << 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/filtersjb/FGFCSComponent.h b/src/FDM/JSBSim/filtersjb/FGFCSComponent.h
deleted file mode 100644 (file)
index f624b20..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGFCSComponent.h
- Author:       Jon S. Berndt
- Date started: 05/01/2000
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGFCSCOMPONENT_H
-#define FGFCSCOMPONENT_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#endif
-
-#include <string>
-#include <vector>
-#include "../FGJSBBase.h"
-#include "../FGPropertyManager.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_FCSCOMPONENT "$Id$"
-
-using std::string;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-class FGFCS;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Base class for JSBSim Flight Control System Components.
-    The Flight Control System (FCS) for JSBSim consists of the FCS container
-    class (see \URL[FGFCS]{FGFCS.html}), the FGFCSComponent base class, and the
-    component classes from which can be constructed a string, or channel. See:
-
-    - FGSwitch
-    - FGGain
-    - FGKinemat
-    - FGFilter
-    - FGDeadBand
-    - FGSummer
-    - FGGradient
-    
-    @author Jon S. Berndt
-    @version $Id$
-    @see Documentation for the FGFCS class, and for the configuration file class
-         FGConfigFile.
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGFCSComponent : public FGJSBBase
-{
-public:
-  /// Constructor
-  FGFCSComponent(FGFCS*);
-  /// Destructor
-  virtual ~FGFCSComponent();
-
-  virtual bool Run(void);
-  virtual void SetOutput(void);
-  inline double GetOutput (void) const {return Output;}
-  inline FGPropertyManager* GetOutputNode(void) { return OutputNode; }
-  inline string GetName(void) const {return Name;}
-  inline string GetType(void) const { return Type; }
-  virtual double GetOutputPct(void) const { return 0; }
-  virtual void convert(void) {};  
-  virtual void bind();
-  FGPropertyManager* resolveSymbol(string token);
-  
-protected:
-  FGFCS* fcs;
-  FGPropertyManager* PropertyManager;
-  FGPropertyManager* treenode;
-  string Type;
-  string Name;
-  vector <FGPropertyManager*> InputNodes;
-  vector <float> InputSigns;
-  double Input;
-  FGPropertyManager* OutputNode;
-  double Output;
-  bool IsOutput;
-  virtual void Debug(int from);
-};
-
-} //namespace JSBSim
-
-#include "../FGFCS.h"
-
-#endif
-
diff --git a/src/FDM/JSBSim/filtersjb/FGFilter.cpp b/src/FDM/JSBSim/filtersjb/FGFilter.cpp
deleted file mode 100644 (file)
index e1a143b..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGFilter.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_FILTER;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
-                                                       AC_cfg(AC_cfg)
-{
-  string token;
-  double denom;
-  string sOutputIdx;
-
-  Type = AC_cfg->GetValue("TYPE");
-  Name = AC_cfg->GetValue("NAME");
-  AC_cfg->GetNextConfigLine();
-  dt = fcs->GetState()->Getdt();
-  Trigger = 0;
-
-  C1 = C2 = C3 = C4 = C5 = C6 = 0.0;
-
-  if      (Type == "LAG_FILTER")          FilterType = eLag        ;
-  else if (Type == "LEAD_LAG_FILTER")     FilterType = eLeadLag    ;
-  else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2     ;
-  else if (Type == "WASHOUT_FILTER")      FilterType = eWashout    ;
-  else if (Type == "INTEGRATOR")          FilterType = eIntegrator ;
-  else                                    FilterType = eUnknown    ;
-
-  while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
-    *AC_cfg >> token;
-    if (token == "C1")           *AC_cfg >> C1;
-    else if (token == "C2")      *AC_cfg >> C2;
-    else if (token == "C3")      *AC_cfg >> C3;
-    else if (token == "C4")      *AC_cfg >> C4;
-    else if (token == "C5")      *AC_cfg >> C5;
-    else if (token == "C6")      *AC_cfg >> C6;
-    else if (token == "TRIGGER")
-    {
-      token = AC_cfg->GetValue("TRIGGER");
-      *AC_cfg >> token;
-      Trigger =  resolveSymbol(token);
-    }
-    else if (token == "INPUT")
-    {
-      token = AC_cfg->GetValue("INPUT");
-      if( InputNodes.size() > 0 ) {
-        cerr << "Filters can only accept one input" << endl;
-      } else  {
-        *AC_cfg >> token;
-        InputNodes.push_back( resolveSymbol(token) );
-      }
-    }
-    else if (token == "OUTPUT")
-    {
-      IsOutput = true;
-      *AC_cfg >> sOutputIdx;
-      OutputNode = PropertyManager->GetNode( sOutputIdx );
-    }
-    else cerr << "Unknown filter type: " << token << endl;
-  }
-
-  Initialize = true;
-
-  switch (FilterType) {
-    case eLag:
-      denom = 2.00 + dt*C1;
-      ca = dt*C1 / denom;
-      cb = (2.00 - dt*C1) / denom;
-      break;
-    case eLeadLag:
-      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*C4) / denom;
-      break;
-    case eOrder2:
-      denom = 4.0*C4 + 2.0*C5*dt + C6*dt*dt;
-      ca = (4.0*C1 + 2.0*C2*dt + C3*dt*dt) / denom;
-      cb = (2.0*C3*dt*dt - 8.0*C1) / denom;
-      cc = (4.0*C1 - 2.0*C2*dt + C3*dt*dt) / denom;
-      cd = (2.0*C6*dt*dt - 8.0*C4) / denom;
-      ce = (4.0*C4 - 2.0*C5*dt + C6*dt*dt) / denom;
-      break;
-    case eWashout:
-      denom = 2.00 + dt*C1;
-      ca = 2.00 / denom;
-      cb = (2.00 - dt*C1) / denom;
-      break;
-    case eIntegrator:
-      ca = dt*C1 / 2.00;
-      break;
-    case eUnknown:
-      cerr << "Unknown filter type" << endl;
-    break;
-  }
-  FGFCSComponent::bind();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGFilter::~FGFilter()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGFilter::Run(void)
-{
-  int test = 0;
-
-  FGFCSComponent::Run(); // call the base class for initialization of Input
-
-  if (Initialize) {
-
-    PreviousOutput1 = PreviousInput1 = Output = Input;
-    Initialize = false;
-
-  } else if (Trigger != 0) {
-    test = Trigger->getIntValue();
-    if (test < 0) {
-      Input  = PreviousInput1 = PreviousInput2 = 0.0;
-    } else {
-      Output = PreviousOutput1 = PreviousOutput2 = 0.0;
-    }
-
-  } else {
-    Input = InputNodes[0]->getDoubleValue();
-    switch (FilterType) {
-      case eLag:
-        Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb;
-        break;
-      case eLeadLag:
-        Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc;
-        break;
-      case eOrder2:
-        Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc
-                            - PreviousOutput1 * cd - PreviousOutput2 * ce;
-        break;
-      case eWashout:
-        Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
-        break;
-      case eIntegrator:
-        Output = Input * ca + PreviousInput1 * ca + PreviousOutput1;
-        break;
-      case eUnknown:
-        break;
-    }
-
-  }
-
-  PreviousOutput2 = PreviousOutput1;
-  PreviousOutput1 = Output;
-  PreviousInput2  = PreviousInput1;
-  PreviousInput1  = Input;
-
-  if (IsOutput) SetOutput();
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGFilter::convert(void)
-{
-  cout << endl;
-  cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
-
-  cout << "            <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
-
-  if (C1 != 0) cout << "            <c1>" << C1 << "</c1>" << endl;
-  if (C2 != 0) cout << "            <c2>" << C2 << "</c2>" << endl;
-  if (C3 != 0) cout << "            <c3>" << C3 << "</c3>" << endl;
-  if (C4 != 0) cout << "            <c4>" << C4 << "</c4>" << endl;
-  if (C5 != 0) cout << "            <c5>" << C5 << "</c5>" << endl;
-  if (C6 != 0) cout << "            <c6>" << C6 << "</c6>" << endl;
-
-  if (Trigger != 0) cout << "            <trigger>" << Trigger << "</trigger>" << endl;
-
-  if (IsOutput)
-    cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
-
-  cout << "        </component>" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGFilter::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
-      cout << "      C1: " << C1 << endl;
-      cout << "      C2: " << C2 << endl;
-      cout << "      C3: " << C3 << endl;
-      cout << "      C4: " << C4 << endl;
-      cout << "      C5: " << C5 << endl;
-      cout << "      C6: " << C6 << endl;
-      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGFilter" << endl;
-    if (from == 1) cout << "Destroyed:    FGFilter" << 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/filtersjb/FGFilter.h b/src/FDM/JSBSim/filtersjb/FGFilter.h
deleted file mode 100644 (file)
index e919bf1..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGFilter.h
- Author:       Jon S. Berndt
- Date started: 4/2000
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGFILTER_H
-#define FGFILTER_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGFCSComponent.h"
-#include "../FGConfigFile.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_FILTER "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates a filter for the flight control system.
-The filter component can simulate any filter up to second order. The
-Tustin substitution is used to take filter definitions from LaPlace space to the
-time domain. The general format for a filter specification is:
-
-<pre>
-\<COMPONENT NAME="name" TYPE="type">
-  INPUT \<property>
-  C1  \<value>
-  [C2 \<value>]
-  [C3 \<value>]
-  [C4 \<value>]
-  [C5 \<value>]
-  [C6 \<value>]
-  [OUTPUT \<property>]
-\</COMPONENT>
-</pre>
-
-For a lag filter of the form,
-<pre>
-  C1
-------
-s + C1 
-</pre>
-the corresponding filter definition is:
-<pre>
-\<COMPONENT NAME="name" TYPE="LAG_FILTER">
-  INPUT \<property>
-  C1 \<value>
-  [OUTPUT \<property>]
-\</COMPONENT>
-</pre>
-As an example, for the specific filter:
-<pre>
-  600
-------
-s + 600 
-</pre>
-the corresponding filter definition could be:
-<pre>
-\<COMPONENT NAME="LAG_1" TYPE="LAG_FILTER">
-  INPUT aileron_cmd
-  C1 600
-\</COMPONENT>
-</pre>
-For a lead-lag filter of the form:
-<pre>
-C1*s + C2
----------
-C3*s + C4 
-</pre>
-The corresponding filter definition is:
-<pre>
-\<COMPONENT NAME="name" TYPE="LEAD_LAG_FILTER">
-  INPUT \<property>
-  C1 \<value>
-  C2 \<value>
-  C3 \<value>
-  C4 \<value>
-  [OUTPUT \<property>]
-\</COMPONENT>
-</pre>
-For a washout filter of the form:
-<pre>
-  s
-------
-s + C1 
-</pre>
-The corresponding filter definition is:
-<pre>
-\<COMPONENT NAME="name" TYPE="WASHOUT_FILTER">
-  INPUT \<property>
-  C1 \<value>
-  [OUTPUT \<property>]
-\</COMPONENT>
-</pre>
-For a second order filter of the form:
-<pre>
-C1*s^2 + C2*s + C3
-------------------
-C4*s^2 + C5*s + C6
-</pre>
-The corresponding filter definition is:
-<pre>
-\<COMPONENT NAME="name" TYPE="SECOND_ORDER_FILTER">
-  INPUT \<property>
-  C1 \<value>
-  C2 \<value>
-  C3 \<value>
-  C4 \<value>
-  C5 \<value>
-  C6 \<value>
-  [OUTPUT \<property>]
-\</COMPONENT>
-</pre>
-For an integrator of the form:
-<pre>
- C1
- ---
-  s
-</pre>
-The corresponding filter definition is:
-<pre>
-\<COMPONENT NAME="name" TYPE="INTEGRATOR">
-  INPUT \<property>
-  C1 \<value>
-  [OUTPUT \<property>]
-  [TRIGGER \<property>]
-\</COMPONENT>
-</pre>
-For the integrator, the TRIGGER features the following behavior, if the TRIGGER
-property value is:
-  - -1 (or simply less than zero), all previous inputs and outputs are set to 0.0
-  - 0, no action is taken - the output is calculated normally
-  - +1 (or simply greater than zero), all previous outputs (only) will be set to 0.0
-
-In all the filter specifications above, an [OUTPUT] keyword is also seen.  This
-is so that the last component in a "string" can copy its value to the appropriate
-output, such as the elevator, or speedbrake, etc.
-
-@author Jon S. Berndt
-@version $Id$
-*/
-   
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGFilter  : public FGFCSComponent         
-{
-public:
-  FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg);
-  ~FGFilter();
-
-  bool Run (void);
-
-  /** When true, causes previous values to be set to current values. This
-      is particularly useful for first pass. */
-  bool Initialize;
-  void convert(void);
-
-  enum {eLag, eLeadLag, eOrder2, eWashout, eIntegrator, eUnknown} FilterType;
-
-private:
-  double dt;
-  double ca;
-  double cb;
-  double cc;
-  double cd;
-  double ce;
-  double C1;
-  double C2;
-  double C3;
-  double C4;
-  double C5;
-  double C6;
-  double PreviousInput1;
-  double PreviousInput2;
-  double PreviousOutput1;
-  double PreviousOutput2;
-  FGConfigFile* AC_cfg;
-  FGPropertyManager* Trigger;
-  void Debug(int from);
-};
-}
-#endif
-
diff --git a/src/FDM/JSBSim/filtersjb/FGGain.cpp b/src/FDM/JSBSim/filtersjb/FGGain.cpp
deleted file mode 100644 (file)
index 79b8611..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- 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
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGGain.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_GAIN;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
-                                                   AC_cfg(AC_cfg)
-{
-  string token;
-  string strScheduledBy;
-  string sOutputIdx;
-
-  State = fcs->GetState();
-
-  Gain = 1.000;
-  Rows = 0;
-  Min = Max = 0.0;
-  OutputPct = 0;
-  invert = false;
-  ScheduledBy = 0;
-  clip = false;
-  clipmin = clipmax = 0.0;
-
-  Type = AC_cfg->GetValue("TYPE");
-  Name = AC_cfg->GetValue("NAME");
-  AC_cfg->GetNextConfigLine();
-
-  while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
-    *AC_cfg >> token;
-    if (token == "INPUT") {
-      *AC_cfg >> token;
-
-      if (token[0] == '-') {
-        invert = true;
-        token.erase(0,1);
-      }
-
-      if (InputNodes.size() > 0) {
-        cerr << "Gains can only accept one input" << endl;
-      } else  {
-        InputNodes.push_back( resolveSymbol(token) );
-      }
-
-    } else if (token == "GAIN") {
-      *AC_cfg >> Gain;
-    } else if (token == "MIN") {
-      *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;
-    } 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 );
-    } else if (token == "OUTPUT") {
-      IsOutput = true;
-      *AC_cfg >> sOutputIdx;
-      OutputNode = PropertyManager->GetNode( sOutputIdx, true );
-    } else {
-      AC_cfg->ResetLineIndexToZero();
-      *Table << *AC_cfg;
-    }
-  }
-
-  FGFCSComponent::bind();
-  if (Type == "AEROSURFACE_SCALE")
-    treenode->Tie( "output-norm", this, &FGGain::GetOutputPct );
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGGain::~FGGain()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGGain::Run(void )
-{
-  double SchedGain = 1.0;
-  double LookupVal = 0;
-
-  FGFCSComponent::Run(); // call the base class for initialization of Input
-  Input = InputNodes[0]->getDoubleValue();
-
-  if (invert) Input = -Input;
-
-  if (Type == "PURE_GAIN") {                       // PURE_GAIN
-
-    Output = Gain * Input;
-
-  } else if (Type == "SCHEDULED_GAIN") {           // SCHEDULED_GAIN
-
-    LookupVal = ScheduledBy->getDoubleValue();
-    SchedGain = Table->GetValue(LookupVal);
-    Output = Gain * SchedGain * Input;
-
-  } else if (Type == "AEROSURFACE_SCALE") {        // AEROSURFACE_SCALE
-
-    OutputPct = Input;
-    if (Input >= 0.0) Output = Input * Max;
-    else Output = Input * -Min;
-    Output *= Gain;
-
-  }
-
-  if (clip) {
-    if (Output > clipmax)      Output = clipmax;
-    else if (Output < clipmin) Output = clipmin;
-  }
-
-  if (IsOutput) SetOutput();
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGGain::convert(void)
-{
-  cout << endl;
-  cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
-
-  if (invert)
-    cout << "            <input>-" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
-  else
-    cout << "            <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
-
-  if (Gain != 1.0)
-    cout << "            <gain>" << Gain << "</gain>" << endl;
-
-  if (Type == "PURE_GAIN") {                       // PURE_GAIN
-  } else if (Type == "SCHEDULED_GAIN") {           // SCHEDULED_GAIN
-    cout << "            <table>" << endl;
-    cout << "                <independentVar>" << ScheduledBy->GetFullyQualifiedName().substr(12) << "</independentVar>" << endl;
-    cout << "                <tableData>" << endl;
-    Table->Print(20);
-    cout << "                </tableData>" << endl;
-    cout << "            </table>" << endl;
-  } else if (Type == "AEROSURFACE_SCALE") {        // AEROSURFACE_SCALE
-    cout << "            <limit>" << endl;
-    cout << "                <min>" << Min << "</min>" << endl;
-    cout << "                <max>" << Max << "</max>" << endl;
-    cout << "            </limit>" << endl;
-  }
-
-  if (clip) {
-    cout << "            <clip>" << endl;
-    cout << "                <min>" << clipmin << "</min>" << endl;
-    cout << "                <max>" << clipmax << "</max>" << endl;
-    cout << "            </clip>" << endl;
-  }
-
-  if (IsOutput)
-    cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
-
-  cout << "        </component>" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGGain::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      if (invert)
-        cout << "      INPUT: -" << InputNodes[0]->getName() << endl;
-      else
-        cout << "      INPUT: " << InputNodes[0]->getName() << endl;
-
-      cout << "      GAIN: " << Gain << endl;
-      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
-      cout << "      MIN: " << Min << endl;
-      cout << "      MAX: " << Max << endl;
-      if (ScheduledBy != 0) {
-        cout << "      Scheduled by parameter: " << ScheduledBy->getName() << endl;
-        Table->Print();
-      }
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGGain" << endl;
-    if (from == 1) cout << "Destroyed:    FGGain" << 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/filtersjb/FGGain.h b/src/FDM/JSBSim/filtersjb/FGGain.h
deleted file mode 100644 (file)
index 0dec3ee..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGGain.h
- Author:
- Date started:
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGGAIN_H
-#define FGGAIN_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  include STL_STRING
-   SG_USING_STD(string);
-#else
-#  include <string>
-#endif
-
-#include "FGFCSComponent.h"
-#include "../FGConfigFile.h"
-#include "../FGTable.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_GAIN "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-class FGFCS;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates a gain component for the flight control system.
-    The gain component merely multiplies the input by a gain.  The form of the
-    gain component specification is:
-    <pre>
-    \<COMPONENT NAME="name" TYPE="PURE_GAIN">
-      INPUT \<property>
-      GAIN  \<value>
-      [OUTPUT \<property>]
-    \</COMPONENT>
-    </pre>
-    Note: as is the case with the Summer component, the input property name may be
-    immediately preceded by a minus sign to invert that signal.
-
-    The scheduled gain component multiplies the input by a variable gain that is
-    dependent on another property (such as qbar, altitude, etc.).  The lookup
-    mapping is in the form of a table.  This kind of component might be used, for
-    example, in a case where aerosurface deflection must only be commanded to
-    acceptable settings - i.e at higher qbar the commanded elevator setting might
-    be attenuated.  The form of the scheduled gain component specification is:
-    <pre>
-    \<COMPONENT NAME="name" TYPE="SCHEDULED_GAIN">
-      INPUT \<property>
-      [GAIN  \<value>]
-      SCHEDULED_BY \<property>
-      ROWS \<number_of_rows>
-      \<lookup_value  gain_value>
-      ?
-      [CLIPTO \<min> \<max> 1]
-      [OUTPUT \<property>]
-    \</COMPONENT>
-    </pre>
-    An overall GAIN may be supplied that is multiplicative with the scheduled gain.
-
-    Note: as is the case with the Summer component, the input property name may
-    be immediately preceded by a minus sign to invert that signal.
-
-    Here is an example of a scheduled gain component specification:
-    <pre>
-    \<COMPONENT NAME="Pitch Scheduled Gain 1" TYPE="SCHEDULED_GAIN">
-      INPUT        fcs/pitch-gain-1
-      GAIN         0.017
-      SCHEDULED_BY fcs/elevator-pos-rad
-      ROWS         22
-      -0.68  -26.548
-      -0.595 -20.513
-      -0.51  -15.328
-      -0.425 -10.993
-      -0.34   -7.508
-      -0.255  -4.873
-      -0.17   -3.088
-      -0.085  -2.153
-       0      -2.068
-       0.085  -2.833
-       0.102  -3.088
-       0.119  -3.377
-       0.136  -3.7
-       0.153  -4.057
-       0.17   -4.448
-       0.187  -4.873
-       0.272  -7.508
-       0.357 -10.993
-       0.442 -15.328
-       0.527 -20.513
-       0.612 -26.548
-       0.697 -33.433
-    \</COMPONENT>
-    </pre>
-    In the example above, we see the utility of the overall GAIN value in
-    effecting a degrees-to-radians conversion.
-
-    The aerosurface scale component is a modified version of the simple gain
-    component.  The normal purpose
-    for this component is to take control inputs that range from -1 to +1 or
-    from 0 to +1 and scale them to match the expected inputs to a flight control
-    system.  For instance, the normal and expected ability of a pilot to push or
-    pull on a control stick is about 50 pounds.  The input to the pitch channelb
-    lock diagram of a flight control system is in units of pounds.  Yet, the
-    joystick control input is usually in a range from -1 to +1.  The form of the
-    aerosurface scaling component specification is:
-<pre>
-    \<COMPONENT NAME="name" TYPE="AEROSURFACE_SCALE">
-      INPUT \<property>
-      MIN \<value>
-      MAX \<value>
-      [GAIN  \<value>]
-      [OUTPUT \<property>]
-    \</COMPONENT>
-</pre>
-    Note: as is the case with the Summer component, the input property name may be
-    immediately preceded by a minus sign to invert that signal.
-
-    @author Jon S. Berndt
-    @version $Id$
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGGain  : public FGFCSComponent
-{
-public:
-  FGGain(FGFCS* fcs, FGConfigFile* AC_cfg);
-  ~FGGain();
-
-  double GetOutputPct() const { return OutputPct; }
-  void convert(void);
-  bool Run (void);
-
-private:
-  FGConfigFile* AC_cfg;
-  FGTable* Table;
-  FGState* State;
-  double Gain;
-  double Min, Max;
-  double clipmin, clipmax;
-  double OutputPct;
-  bool invert, clip;
-  int Rows;
-  FGPropertyManager* ScheduledBy;
-
-  void Debug(int from);
-};
-}
-#endif
diff --git a/src/FDM/JSBSim/filtersjb/FGGradient.cpp b/src/FDM/JSBSim/filtersjb/FGGradient.cpp
deleted file mode 100644 (file)
index 359a9ed..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGGradient.cpp
- Author:       
- Date started: 
- ------------- Copyright (C) 2000 -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGGradient.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_GRADIENT;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGGradient::FGGradient(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
-                                                           AC_cfg(AC_cfg)
-{
-  Type = AC_cfg->GetValue("TYPE");
-  Name = AC_cfg->GetValue("NAME");
-  
-  FGFCSComponent::bind();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGGradient::~FGGradient()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGGradient::Run(void )
-{
-  FGFCSComponent::Run(); // call the base class for initialization of Input
-
-  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 FGGradient::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: FGGradient" << endl;
-    if (from == 1) cout << "Destroyed:    FGGradient" << 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/filtersjb/FGGradient.h b/src/FDM/JSBSim/filtersjb/FGGradient.h
deleted file mode 100644 (file)
index 66ac963..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGGradient.h
- Author:       
- Date started: 
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGGRADIENT_H
-#define FGGRADIENT_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGFCSComponent.h"
-#include "../FGConfigFile.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_GRADIENT "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-class FGFCS;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates a gradient component for the flight control system.
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGGradient  : public FGFCSComponent
-{
-public:
-  FGGradient(FGFCS* fcs, FGConfigFile* AC_cfg);
-  ~FGGradient();
-
-  bool Run (void);
-
-private:
-  FGConfigFile* AC_cfg;
-  void Debug(int from);
-};
-}
-#endif
diff --git a/src/FDM/JSBSim/filtersjb/FGKinemat.cpp b/src/FDM/JSBSim/filtersjb/FGKinemat.cpp
deleted file mode 100644 (file)
index c9b9f46..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGKinemat.cpp
- Author:       Tony Peden, for flight control system authored by Jon S. Berndt
- Date started: 12/02/01
-
- ------------- Copyright (C) 2000 Anthony K. Peden -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <math.h>
-#include <float.h>
-
-#include "FGKinemat.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_FLAPS;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGKinemat::FGKinemat(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
-                                                         AC_cfg(AC_cfg)
-{
-  string token,sOutputIdx;
-  double tmpDetent;
-  double tmpTime;
-
-  Detents.clear();
-  TransitionTimes.clear();
-
-  OutputPct=0;
-  DoScale = true;
-
-  Type = AC_cfg->GetValue("TYPE");
-  Name = AC_cfg->GetValue("NAME");
-  AC_cfg->GetNextConfigLine();
-
-  while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
-    *AC_cfg >> token;
-    if (token == "INPUT") {
-      token = AC_cfg->GetValue("INPUT");
-      if( InputNodes.size() > 0 ) {
-        cerr << "Kinemat can only accept one input" << endl;
-      } else  {
-        *AC_cfg >> token;
-        InputNodes.push_back( resolveSymbol(token) );
-      }
-
-    } else if ( token == "DETENTS" ) {
-      *AC_cfg >> NumDetents;
-      if (NumDetents < 2) {
-        cerr << "Kinemat must have at least 2 DETENTS" << endl;
-      }
-      for (int i=0;i<NumDetents;i++) {
-        *AC_cfg >> tmpDetent;
-        *AC_cfg >> tmpTime;
-        Detents.push_back(tmpDetent);
-        TransitionTimes.push_back(tmpTime);
-      }
-    } else if (token == "OUTPUT") {
-
-      IsOutput = true;
-      *AC_cfg >> sOutputIdx;
-      OutputNode = PropertyManager->GetNode(sOutputIdx, true);
-    } else if (token == "NOSCALE") {
-
-      DoScale = false;
-    }
-  }
-  FGFCSComponent::bind();
-  treenode->Tie("output-norm", this, &FGKinemat::GetOutputPct );
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGKinemat::~FGKinemat()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGKinemat::Run(void )
-{
-  double dt = fcs->GetState()->Getdt();
-
-  Input = InputNodes[0]->getDoubleValue();
-
-  if (DoScale) Input *= Detents[NumDetents-1];
-
-  Output = OutputNode->getDoubleValue();
-
-  if (Input < Detents[0])
-    Input = Detents[0];
-  else if (Detents[NumDetents-1] < Input)
-    Input = Detents[NumDetents-1];
-
-  // Process all detent intervals the movement traverses until either the
-  // final value is reached or the time interval has finished.
-  while ( 0.0 < dt && !EqualToRoundoff(Input, Output) ) {
-
-    // Find the area where Output is in
-    int ind;
-    for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind)
-      if (NumDetents <= ind)
-        break;
-
-    // A transition time of 0.0 means an infinite rate.
-    // The output is reached in one step
-    if (TransitionTimes[ind] <= 0.0) {
-      Output = Input;
-      break;
-    } else {
-      // Compute the rate in this area
-      double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind];
-      // Compute the maximum input value inside this area
-      double ThisInput = Input;
-      if (ThisInput < Detents[ind-1])   ThisInput = Detents[ind-1];
-      if (Detents[ind] < ThisInput)     ThisInput = Detents[ind];
-      // Compute the time to reach the value in ThisInput
-      double ThisDt = fabs((ThisInput-Output)/Rate);
-
-      // and clip to the timestep size
-      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;
-    }
-  }
-
-  OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]);
-
-  if (IsOutput) SetOutput();
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGKinemat::convert(void)
-{
-  cout << endl;
-  cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
-
-  cout << "            <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
-
-  cout << "            <traverse>" << endl;
-  for (int i=0; i<Detents.size(); i++) {
-    cout << "                <setting>" << endl;
-    cout << "                    <position>" << Detents[i] << "</position>" << endl;
-    cout << "                    <time>" << TransitionTimes[i] << "</time>" << endl;
-    cout << "                </setting>" << endl;
-  }
-  cout << "            </traverse>" << endl;
-
-  if (IsOutput)
-    cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
-
-  cout << "        </component>" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGKinemat::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
-      cout << "      DETENTS: " << NumDetents << endl;
-      for (int i=0;i<NumDetents;i++) {
-        cout << "        " << Detents[i] << " " << TransitionTimes[i] << endl;
-      }
-      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
-      if (!DoScale) cout << "      NOSCALE" << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGKinemat" << endl;
-    if (from == 1) cout << "Destroyed:    FGKinemat" << 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/filtersjb/FGKinemat.h b/src/FDM/JSBSim/filtersjb/FGKinemat.h
deleted file mode 100644 (file)
index a438b55..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Header:       FGKinemat.h
- Author:       Tony Peden, for flight control system authored by Jon S. Berndt
- Date started: 12/02/01 
- ------------- Copyright (C) Anthony K. Peden -------------
- 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
---------------------------------------------------------------------------------
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGKinemat_H
-#define FGKinemat_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <vector>
-#  else
-#    include <vector.h>
-#  endif
-#else
-#  include <vector>
-#endif
-
-#include <string>
-#include "FGFCSComponent.h"
-#include "../FGConfigFile.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_FLAPS "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates a kinematic component for the flight control system.
-  */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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);
-  void convert(void);
-
-private:
-  FGConfigFile* AC_cfg;
-  vector<double> Detents;
-  vector<double> TransitionTimes;
-  int NumDetents;
-  double OutputPct;
-  bool  DoScale;
-
-  void Debug(int from);
-};
-}
-#endif
diff --git a/src/FDM/JSBSim/filtersjb/FGSummer.cpp b/src/FDM/JSBSim/filtersjb/FGSummer.cpp
deleted file mode 100644 (file)
index 68b8fa6..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGSummer.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
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGSummer.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_SUMMER;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGSummer::FGSummer(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
-                                                       AC_cfg(AC_cfg)
-{
-  string token,sOutputIdx;
-
-  clip = false;
-  clipmin = clipmax = 0.0;
-  Bias = 0.0;
-
-  Type = AC_cfg->GetValue("TYPE");
-  Name = AC_cfg->GetValue("NAME");
-  AC_cfg->GetNextConfigLine();
-
-  while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
-    *AC_cfg >> token;
-
-    if (token == "INPUT") {
-      token = AC_cfg->GetValue("INPUT");
-      *AC_cfg >> token;
-
-      if (token[0] == '-') {
-        InputSigns.push_back(-1.0);
-        token.erase(0,1);
-      } else {
-        InputSigns.push_back( 1.0);
-      }
-
-      InputNodes.push_back( resolveSymbol(token) );
-    } else if (token == "BIAS") {
-      *AC_cfg >> Bias;
-    } else if (token == "CLIPTO") {
-      *AC_cfg >> clipmin >> clipmax;
-      if (clipmax > clipmin) {
-        clip = true;
-      }
-    } else if (token == "OUTPUT") {
-      IsOutput = true;
-      *AC_cfg >> sOutputIdx;
-      OutputNode = PropertyManager->GetNode(sOutputIdx, true);
-    }
-  }
-
-  FGFCSComponent::bind();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGSummer::~FGSummer()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGSummer::Run(void )
-{
-  unsigned int idx;
-
-  // The Summer takes several inputs, so do not call the base class Run()
-  // FGFCSComponent::Run();
-
-  Output = 0.0;
-
-  for (idx=0; idx<InputNodes.size(); idx++) {
-    Output += InputNodes[idx]->getDoubleValue()*InputSigns[idx];
-  }
-
-  Output += Bias;
-
-  if (clip) {
-    if (Output > clipmax)      Output = clipmax;
-    else if (Output < clipmin) Output = clipmin;
-  }
-
-  if (IsOutput) SetOutput();
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGSummer::convert(void)
-{
-  string sSign;
-
-  cout << endl;
-  cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
-
-  for (int i=0; i<InputNodes.size(); i++) {
-    if (InputSigns[i] < 0.0) sSign = "-";
-    else                     sSign = "";
-    cout << "            <input>" << sSign << (InputNodes[i]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
-  }
-
-  if (Bias != 0.0)
-    cout << "            <bias>" << Bias << "</bias>" << endl;
-
-  if (clip) {
-    cout << "            <clip>" << endl;
-    cout << "                <min>" << clipmin << "</min>" << endl;
-    cout << "                <max>" << clipmax << "</max>" << endl;
-    cout << "            </clip>" << endl;
-  }
-
-  if (IsOutput)
-    cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
-
-  cout << "        </component>" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGSummer::Debug(int from)
-{
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      cout << "      INPUTS: " << endl;
-      for (unsigned i=0;i<InputNodes.size();i++) {
-        if (InputSigns[i] < 0)
-          cout << "       -" << InputNodes[i]->getName() << endl;
-        else
-          cout << "       " << InputNodes[i]->getName() << endl;
-      }
-      if (Bias != 0.0) cout << "       Bias: " << Bias << endl;
-      if (clip) cout << "      CLIPTO: " << clipmin
-                                  << ", " << clipmax << endl;
-      if (IsOutput) cout << "      OUTPUT: " <<OutputNode->getName() <<  endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGSummer" << endl;
-    if (from == 1) cout << "Destroyed:    FGSummer" << 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;
-    }
-  }
-}
-
-} //namespace JSBSim
-
diff --git a/src/FDM/JSBSim/filtersjb/FGSummer.h b/src/FDM/JSBSim/filtersjb/FGSummer.h
deleted file mode 100644 (file)
index 7ee68c6..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGSummer.h
- Author:       
- Date started: 
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGSUMMER_H
-#define FGSUMMER_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-#  include <simgear/compiler.h>
-#  ifdef SG_HAVE_STD_INCLUDES
-#    include <vector>
-#  else
-#    include <vector.h>
-#  endif
-#else
-#  include <vector>
-#endif
-
-#include <string>
-#include "FGFCSComponent.h"
-#include "../FGConfigFile.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_SUMMER "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models a flight control system summing component.
-    The Summer component sums two or more inputs. These can be pilot control
-    inputs or state variables, and a bias can also be added in using the BIAS
-    keyword.  The form of the summer component specification is:
-<pre>
-    \<COMPONENT NAME="name" TYPE="SUMMER">
-      INPUT \<property>
-      INPUT \<property>
-      [BIAS \<value>]
-      [?]
-      [CLIPTO \<min> \<max> 1]
-      [OUTPUT \<property>]
-    \</COMPONENT>
-</pre>
-    Note that in the case of an input property the property name may be
-    immediately preceded by a minus sign. Here's an example of a summer
-    component specification:
-<pre>
-    \<COMPONENT NAME="Roll A/P Error summer" TYPE="SUMMER">
-      INPUT  velocities/p-rad_sec
-      INPUT -fcs/roll-ap-wing-leveler
-      INPUT  fcs/roll-ap-error-integrator
-      CLIPTO -1 1
-    \</COMPONENT>
-</pre>
-    Note that there can be only one BIAS statement per component.
-    
-    @author Jon S. Berndt
-    @version $Id$
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGSummer  : public FGFCSComponent
-{
-public:
-  /** Constructor.
-      @param fcs a pointer to the parent FGFCS object.
-      @param AC_cfg a pointer to the configuration file object. */
-  FGSummer(FGFCS* fcs, FGConfigFile* AC_cfg);
-  /// Destructor
-  ~FGSummer();
-
-  /// The execution method for this FCS component.
-  bool Run(void);
-  void convert(void);
-
-private:
-  FGConfigFile* AC_cfg;
-  bool clip;
-  double clipmin,clipmax;
-  double Bias;
-  void Debug(int from);
-};
-}
-#endif
diff --git a/src/FDM/JSBSim/filtersjb/FGSwitch.cpp b/src/FDM/JSBSim/filtersjb/FGSwitch.cpp
deleted file mode 100644 (file)
index ca5058d..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module:       FGSwitch.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
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES,  and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-The SWITCH component is defined as follows (see the API documentation for more
-information):
-
-<COMPONENT NAME="switch1" TYPE="SWITCH">
-  <TEST LOGIC="{AND|OR|DEFAULT}" OUTPUT="{property|value}">
-    {property} {conditional} {property|value}
-    <CONDITION_GROUP LOGIC="{AND|OR}">
-      {property} {conditional} {property|value}
-      ...
-    </CONDITION_GROUP>
-    ...
-  </TEST>
-  <TEST LOGIC="{AND|OR}" OUTPUT="{property|value}">
-    {property} {conditional} {property|value}
-    ...
-  </TEST>
-  ...
-</COMPONENT>
-
-Also, see the header file (FGSwitch.h) for further details.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FGSwitch.h"
-
-namespace JSBSim {
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_SWITCH;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
-                                                       AC_cfg(AC_cfg)
-{
-  string token, value;
-  struct test *current_test;
-  string sOutputIdx;
-
-  Type = AC_cfg->GetValue("TYPE");
-  Name = AC_cfg->GetValue("NAME");
-
-  AC_cfg->GetNextConfigLine();
-  while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
-
-    // See the above documentation, or the API docs, for information on what
-    // the SWITCH component is supposed to look like in the configuration file.
-    // Below, the switch component is read in.
-
-    if (token == "TEST") {
-      tests.push_back(test());
-      current_test = &tests.back();
-
-      if (AC_cfg->GetValue("LOGIC") == "OR") {
-        current_test->Logic = eOR;
-      } else if (AC_cfg->GetValue("LOGIC") == "AND") {
-        current_test->Logic = eAND;
-      } else if (AC_cfg->GetValue("LOGIC") == "DEFAULT") {
-        current_test->Logic = eDefault;
-      } else { // error
-        cerr << "Unrecognized LOGIC token  in switch component: " << Name << endl;
-      }
-
-      value = AC_cfg->GetValue("VALUE");
-      if (value.empty()) {
-        cerr << "No VALUE supplied for switch component: " << Name << endl;
-      } else {
-        if (value.find_first_not_of("-.0123456789eE") == string::npos) {
-          // if true (and execution falls into this block), "value" is a number.
-          current_test->OutputVal = atof(value.c_str());
-        } else {
-          // "value" must be a property if execution passes to here.
-          if (value[0] == '-') {
-            current_test->sign = -1.0;
-            value.erase(0,1);
-          } else {
-            current_test->sign = 1.0;
-          }
-          current_test->OutputProp = PropertyManager->GetNode(value);
-        }
-      }
-
-      AC_cfg->GetNextConfigLine();
-      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 );
-    }
-  }
-
-  FGFCSComponent::bind();
-
-  Debug(0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGSwitch::~FGSwitch()
-{
-  Debug(1);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-bool FGSwitch::Run(void )
-{
-  vector <test>::iterator iTests = tests.begin();
-  vector <FGCondition>::iterator iConditions;
-  bool pass = false;
-
-  FGFCSComponent::Run(); // call the base class for initialization of Input
-
-  while (iTests < tests.end()) {
-    iConditions = iTests->conditions.begin();
-
-    if (iTests->Logic == eDefault) {
-      Output = iTests->GetValue();
-    } else if (iTests->Logic == eAND) {
-      pass = true;
-      while (iConditions < iTests->conditions.end()) {
-        if (!iConditions->Evaluate()) pass = false;
-        *iConditions++;
-      }
-    } else if (iTests->Logic == eOR) {
-      pass = false;
-      while (iConditions < iTests->conditions.end()) {
-        if (iConditions->Evaluate()) pass = true;
-        *iConditions++;
-      }
-    } else {
-      cerr << "Invalid logic test" << endl;
-    }
-
-    if (pass) {
-      Output = iTests->GetValue();
-      break;
-    }
-    *iTests++;
-  }
-
-  if (IsOutput) SetOutput();
-
-  return true;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGSwitch::convert(void)
-{
-  cout << endl;
-  cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
-
-//  cout << "            <input>" << InputNodes[0]->GetName() << "</input>" << endl;
-
-  for (int i=0; i<tests.size(); i++) {
-    if (tests[i].Logic == eDefault) {
-      if (tests[i].OutputProp == 0L)
-        cout << "            <default value=\"" << tests[i].OutputVal << "\"/>" << endl;
-      else
-        cout << "            <default value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\"/>" << endl;
-    } else if (tests[i].Logic == eAND) {
-      if (tests[i].OutputProp == 0L)
-        cout << "            <test logic=\"AND\" value=\"" << tests[i].OutputVal << "\">" << endl;
-      else
-        cout << "            <test logic=\"AND\" value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\">" << endl;
-    } else if (tests[i].Logic == eOR) {
-      if (tests[i].OutputProp == 0L)
-        cout << "            <test logic=\"OR\" value=\"" << tests[i].OutputVal << "\">" << endl;
-      else
-        cout << "            <test logic=\"OR\" value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\">" << endl;
-    }
-    for (int j=0; j<tests[i].conditions.size(); j++) {
-      tests[i].conditions[j].convert();
-    }
-    if (tests[i].Logic != eDefault) cout << "            </test>" << endl;
-  }
-
-  if (IsOutput)
-    cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
-
-  cout << "        </component>" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//    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 FGSwitch::Debug(int from)
-{
-  vector <test>::iterator iTests = tests.begin();
-  vector <FGCondition>::iterator iConditions;
-  string comp, scratch;
-  string indent = "        ";
-  bool first = false;
-
-  if (debug_lvl <= 0) return;
-
-  if (debug_lvl & 1) { // Standard console startup message output
-    if (from == 0) { // Constructor
-      while (iTests < tests.end()) {
-
-        scratch = " if ";
-
-        switch(iTests->Logic) {
-        case (elUndef):
-          comp = " UNSET ";
-          cerr << "Unset logic for test condition" << endl;
-          break;
-        case (eAND):
-          comp = " AND ";
-          break;
-        case (eOR):
-          comp=" OR ";
-          break;
-        case (eDefault):
-          scratch = " by default.";
-          break;
-        default:
-          comp = " UNKNOWN ";
-          cerr << "Unknown logic for test condition" << endl;
-        }
-
-        if (iTests->OutputProp != 0L)
-          if (iTests->sign < 0)
-            cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
-          else
-            cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
-        else
-          cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
-
-        iConditions = iTests->conditions.begin();
-        first = true;
-        while (iConditions < iTests->conditions.end()) {
-          if (!first) cout << indent << comp << " ";
-          else cout << indent << " ";
-          first = false;
-          iConditions->PrintCondition();
-          cout << endl;
-          *iConditions++;
-        }
-        cout << endl;
-        *iTests++;
-      }
-      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
-    }
-  }
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
-    if (from == 0) cout << "Instantiated: FGSwitch" << endl;
-    if (from == 1) cout << "Destroyed:    FGSwitch" << 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;
-    }
-  }
-}
-
-} //namespace JSBSim
-
diff --git a/src/FDM/JSBSim/filtersjb/FGSwitch.h b/src/FDM/JSBSim/filtersjb/FGSwitch.h
deleted file mode 100644 (file)
index a942a8d..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header:       FGSwitch.h
- Author:       Jon S. Berndt
- Date started: 12/23/2002
-
- ------------- Copyright (C)  -------------
-
- 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
---------------------------------------------------------------------------------
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGSWITCH_H
-#define FGSWITCH_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGFCSComponent.h"
-#include "../FGConfigFile.h"
-#include "FGCondition.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_SWITCH "$Id$"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-namespace JSBSim {
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Encapsulates a switch for the flight control system.
-
-The SWITCH component models a switch - either on/off or a multi-choice rotary
-switch. The switch can represent a physical cockpit switch, or can represent a
-logical switch, where several conditions might need to be satisfied before a
-particular state is reached. The VALUE of the switch - the output value for the
-component - is chosen depending on the state of the switch. Each switch is
-comprised of two or more TESTs. Each TEST has a VALUE associated with it. The
-first TEST that evaluates to TRUE will set the output value of the switch
-according to the VALUE parameter belonging to that TEST. Each TEST contains one
-or more CONDITIONS, which each must be logically related (if there are more than
-one) given the value of the LOGIC parameter, and which takes the form:
-
-  property conditional property|value
-
-e.g.
-
-  qbar GE 21.0
-
-or,
-
-  roll_rate < pitch_rate
-
-Within a TEST, a CONDITION_GROUP can be specified. A CONDITION_GROUP allows for
-complex groupings of logical comparisons. Each CONDITION_GROUP contains
-additional conditions, as well as possibly additional CONDITION_GROUPs.
-
-<pre>
-\<COMPONENT NAME="switch1" TYPE="SWITCH"\>
-  \<TEST LOGIC="{AND|OR|DEFAULT}" VALUE="{property|value}"\>
-    {property} {conditional} {property|value}
-    \<CONDITION_GROUP LOGIC="{AND|OR}"\>
-      {property} {conditional} {property|value}
-      ...
-    \</CONDITION_GROUP\>
-    ...
-  \</TEST>
-  \<TEST LOGIC="{AND|OR}" VALUE="{property|value}"\>
-    {property} {conditional} {property|value}
-    ...
-  \</TEST\>
-  ...
-  [OUTPUT \<property>]
-\</COMPONENT\>
-</pre>
-
-Here's an example:
-<pre>
-\<COMPONENT NAME="Roll A/P Autoswitch" TYPE="SWITCH">
-  \<TEST LOGIC="DEFAULT" VALUE="0.0">
-  \</TEST>
-  \<TEST LOGIC="AND" VALUE="fcs/roll-ap-error-summer">
-    ap/attitude_hold == 1
-  \</TEST>
-\</COMPONENT>
-</pre>
-The above example specifies that the default value of the component (i.e. the
-output property of the component, addressed by the property, ap/roll-ap-autoswitch)
-is 0.0.  If or when the attitude hold switch is selected (property
-ap/attitude_hold takes the value 1), the value of the switch component will be
-whatever value fcs/roll-ap-error-summer is.
-@author Jon S. Berndt
-@version $Id$
-*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGSwitch  : public FGFCSComponent
-{
-public:
-  FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg);
-  ~FGSwitch();
-
-  bool Run(void);
-  void convert(void);
-
-  enum eLogic {elUndef=0, eAND, eOR, eDefault};
-  enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE};
-
-private:
-  FGFCS* fcs;
-  FGConfigFile* AC_cfg;
-
-  struct test {
-    vector <FGCondition> conditions;
-    eLogic Logic;
-    double OutputVal;
-    FGPropertyManager *OutputProp;
-    float sign;
-
-    double GetValue(void) {
-      if (OutputProp == 0L) return OutputVal;
-      else                  return OutputProp->getDoubleValue()*sign;
-    }
-
-    test(void) { // constructor for the test structure
-      Logic      = elUndef;
-      OutputVal  = 0.0;
-      OutputProp = 0L;
-      sign       = 1.0;
-    }
-
-  };
-
-  vector <test> tests;
-
-  void Debug(int from);
-};
-}
-#endif
diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp
new file mode 100644 (file)
index 0000000..0053838
--- /dev/null
@@ -0,0 +1,1077 @@
+/*******************************************************************************
+
+ Header:       FGInitialCondition.cpp
+ Author:       Tony Peden
+ Date started: 7/1/99
+
+ ------------- 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/1/99   TP   Created
+
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+The purpose of this class is to take a set of initial conditions and provide
+a kinematically consistent set of body axis velocity components, euler
+angles, and altitude.  This class does not attempt to trim the model i.e.
+the sim will most likely start in a very dynamic state (unless, of course,
+you have chosen your IC's wisely) even after setting it up with this class.
+
+********************************************************************************
+INCLUDES
+*******************************************************************************/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <fstream>
+#  else
+#    include <fstream.h>
+#  endif
+#else
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <fstream.h>
+#  else
+#    include <fstream>
+#  endif
+#endif
+
+#include "FGInitialCondition.h"
+#include <FGFDMExec.h>
+#include <models/FGInertial.h>
+#include <models/FGAtmosphere.h>
+#include <models/FGAerodynamics.h>
+#include <models/FGPropagate.h>
+#include <input_output/FGPropertyManager.h>
+#include <models/FGPropulsion.h>
+#include <input_output/FGXMLParse.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_INITIALCONDITION;
+
+//******************************************************************************
+
+FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec)
+{
+  vt=vc=ve=vg=0;
+  mach=0;
+  alpha=beta=gamma=0;
+  theta=phi=psi=0;
+  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;
+  whead=wcross=0;
+  wdir=wmag=0;
+  lastSpeedSet=setvt;
+  lastWindSet=setwned;
+  sea_level_radius = FDMExec->GetInertial()->RefRadius();
+  radius_to_vehicle = FDMExec->GetInertial()->RefRadius();
+  terrain_altitude = 0;
+
+  salpha=sbeta=stheta=sphi=spsi=sgamma=0;
+  calpha=cbeta=ctheta=cphi=cpsi=cgamma=1;
+
+  if(FDMExec != NULL ) {
+    fdmex=FDMExec;
+    fdmex->GetPropagate()->Seth(altitude);
+    fdmex->GetAtmosphere()->Run();
+    PropertyManager=fdmex->GetPropertyManager();
+    bind();
+  } else {
+    cout << "FGInitialCondition: This class requires a pointer to a valid FGFDMExec object" << endl;
+  }
+
+  Debug(0);
+}
+
+//******************************************************************************
+
+FGInitialCondition::~FGInitialCondition()
+{
+  unbind();
+  Debug(1);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVcalibratedKtsIC(double tt) {
+
+  if(getMachFromVcas(&mach,tt*ktstofps)) {
+    //cout << "Mach: " << mach << endl;
+    lastSpeedSet=setvc;
+    vc=tt*ktstofps;
+    vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
+    ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+    //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
+  }
+  else {
+    cout << "Failed to get Mach number for given Vc and altitude, Vc unchanged." << endl;
+    cout << "Please mail the set of initial conditions used to apeden@earthlink.net" << endl;
+  }
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVequivalentKtsIC(double tt) {
+  ve=tt*ktstofps;
+  lastSpeedSet=setve;
+  vt=ve*1/sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+  mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
+  vc=calcVcas(mach);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVgroundFpsIC(double tt) {
+  double ua,va,wa;
+  double vxz;
+
+  vg=tt;
+  lastSpeedSet=setvg;
+  vnorth = vg*cos(psi); veast = vg*sin(psi); vdown = 0;
+  calcUVWfromNED();
+  ua = u + uw; va = v + vw; wa = w + ww;
+  vt = sqrt( ua*ua + va*va + wa*wa );
+  alpha = beta = 0;
+  vxz = sqrt( u*u + w*w );
+  if( w != 0 ) alpha = atan2( w, u );
+  if( vxz != 0 ) beta = atan2( v, vxz );
+  mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
+  vc=calcVcas(mach);
+  ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVtrueFpsIC(double tt) {
+  vt=tt;
+  lastSpeedSet=setvt;
+  mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
+  vc=calcVcas(mach);
+  ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetMachIC(double tt) {
+  mach=tt;
+  lastSpeedSet=setmach;
+  vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
+  vc=calcVcas(mach);
+  ve=vt*sqrt(fdmex->GetAtmosphere()->GetDensityRatio());
+  //cout << "Vt: " << vt*fpstokts << " Vc: " << vc*fpstokts << endl;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetClimbRateFpmIC(double tt) {
+  SetClimbRateFpsIC(tt/60.0);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetClimbRateFpsIC(double tt) {
+
+  if(vt > 0.1) {
+    hdot=tt;
+    gamma=asin(hdot/vt);
+    sgamma=sin(gamma); cgamma=cos(gamma);
+  }
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetFlightPathAngleRadIC(double tt) {
+  gamma=tt;
+  sgamma=sin(gamma); cgamma=cos(gamma);
+  getTheta();
+  hdot=vt*sgamma;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetAlphaRadIC(double tt) {
+  alpha=tt;
+  salpha=sin(alpha); calpha=cos(alpha);
+  getTheta();
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetPitchAngleRadIC(double tt) {
+  theta=tt;
+  stheta=sin(theta); ctheta=cos(theta);
+  getAlpha();
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetBetaRadIC(double tt) {
+  beta=tt;
+  sbeta=sin(beta); cbeta=cos(beta);
+  getTheta();
+
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetRollAngleRadIC(double tt) {
+  phi=tt;
+  sphi=sin(phi); cphi=cos(phi);
+  getTheta();
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetTrueHeadingRadIC(double tt) {
+    psi=tt;
+    spsi=sin(psi); cpsi=cos(psi);
+    calcWindUVW();
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetUBodyFpsIC(double tt) {
+  u=tt;
+  vt=sqrt(u*u + v*v + w*w);
+  lastSpeedSet=setuvw;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVBodyFpsIC(double tt) {
+  v=tt;
+  vt=sqrt(u*u + v*v + w*w);
+  lastSpeedSet=setuvw;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetWBodyFpsIC(double tt) {
+  w=tt;
+  vt=sqrt( u*u + v*v + w*w );
+  lastSpeedSet=setuvw;
+}
+
+//******************************************************************************
+
+double FGInitialCondition::GetUBodyFpsIC(void) const {
+    if(lastSpeedSet == setvg )
+      return u;
+    else
+      return vt*calpha*cbeta - uw;
+}
+
+//******************************************************************************
+
+double FGInitialCondition::GetVBodyFpsIC(void) const {
+    if( lastSpeedSet == setvg )
+      return v;
+    else {
+      return vt*sbeta - vw;
+    }
+}
+
+//******************************************************************************
+
+double FGInitialCondition::GetWBodyFpsIC(void) const {
+    if( lastSpeedSet == setvg )
+      return w;
+    else
+      return vt*salpha*cbeta -ww;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetWindNEDFpsIC(double wN, double wE, double wD ) {
+  wnorth = wN; weast = wE; wdown = wD;
+  lastWindSet = setwned;
+  calcWindUVW();
+  if(lastSpeedSet == setvg)
+    SetVgroundFpsIC(vg);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetCrossWindKtsIC(double cross){
+    wcross=cross*ktstofps;
+    lastWindSet=setwhc;
+    calcWindUVW();
+    if(lastSpeedSet == setvg)
+      SetVgroundFpsIC(vg);
+
+}
+
+//******************************************************************************
+
+// positive from left
+void FGInitialCondition::SetHeadWindKtsIC(double head){
+    whead=head*ktstofps;
+    lastWindSet=setwhc;
+    calcWindUVW();
+    if(lastSpeedSet == setvg)
+      SetVgroundFpsIC(vg);
+
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetWindDownKtsIC(double wD) {
+    wdown=wD;
+    calcWindUVW();
+    if(lastSpeedSet == setvg)
+      SetVgroundFpsIC(vg);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetWindMagKtsIC(double mag) {
+  wmag=mag*ktstofps;
+  lastWindSet=setwmd;
+  calcWindUVW();
+  if(lastSpeedSet == setvg)
+      SetVgroundFpsIC(vg);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetWindDirDegIC(double dir) {
+  wdir=dir*degtorad;
+  lastWindSet=setwmd;
+  calcWindUVW();
+  if(lastSpeedSet == setvg)
+      SetVgroundFpsIC(vg);
+}
+
+
+//******************************************************************************
+
+void FGInitialCondition::calcWindUVW(void) {
+
+    switch(lastWindSet) {
+      case setwmd:
+        wnorth=wmag*cos(wdir);
+        weast=wmag*sin(wdir);
+      break;
+      case setwhc:
+        wnorth=whead*cos(psi) + wcross*cos(psi+M_PI/2);
+        weast=whead*sin(psi) + wcross*sin(psi+M_PI/2);
+      break;
+      case setwned:
+      break;
+    }
+    uw=wnorth*ctheta*cpsi +
+       weast*ctheta*spsi -
+       wdown*stheta;
+    vw=wnorth*( sphi*stheta*cpsi - cphi*spsi ) +
+        weast*( sphi*stheta*spsi + cphi*cpsi ) +
+       wdown*sphi*ctheta;
+    ww=wnorth*(cphi*stheta*cpsi + sphi*spsi) +
+       weast*(cphi*stheta*spsi - sphi*cpsi) +
+       wdown*cphi*ctheta;
+
+
+    /* cout << "FGInitialCondition::calcWindUVW: wnorth, weast, wdown "
+         << wnorth << ", " << weast << ", " << wdown << endl;
+    cout << "FGInitialCondition::calcWindUVW: theta, phi, psi "
+          << theta << ", " << phi << ", " << psi << endl;
+    cout << "FGInitialCondition::calcWindUVW: uw, vw, ww "
+          << uw << ", " << vw << ", " << ww << endl; */
+
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetAltitudeFtIC(double tt) {
+  altitude=tt;
+  fdmex->GetPropagate()->Seth(altitude);
+  fdmex->GetAtmosphere()->Run();
+  //lets try to make sure the user gets what they intended
+
+  switch(lastSpeedSet) {
+  case setned:
+  case setuvw:
+  case setvt:
+    SetVtrueKtsIC(vt*fpstokts);
+    break;
+  case setvc:
+    SetVcalibratedKtsIC(vc*fpstokts);
+    break;
+  case setve:
+    SetVequivalentKtsIC(ve*fpstokts);
+    break;
+  case setmach:
+    SetMachIC(mach);
+    break;
+  case setvg:
+    SetVgroundFpsIC(vg);
+    break;
+  }
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetAltitudeAGLFtIC(double tt) {
+  SetAltitudeFtIC(terrain_altitude + tt);
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) {
+  sea_level_radius = tt;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) {
+  terrain_altitude=tt;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::calcUVWfromNED(void) {
+  u=vnorth*ctheta*cpsi +
+     veast*ctheta*spsi -
+     vdown*stheta;
+  v=vnorth*( sphi*stheta*cpsi - cphi*spsi ) +
+     veast*( sphi*stheta*spsi + cphi*cpsi ) +
+     vdown*sphi*ctheta;
+  w=vnorth*( cphi*stheta*cpsi + sphi*spsi ) +
+     veast*( cphi*stheta*spsi - sphi*cpsi ) +
+     vdown*cphi*ctheta;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVnorthFpsIC(double tt) {
+  vnorth=tt;
+  calcUVWfromNED();
+  vt=sqrt(u*u + v*v + w*w);
+  lastSpeedSet=setned;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVeastFpsIC(double tt) {
+  veast=tt;
+  calcUVWfromNED();
+  vt=sqrt(u*u + v*v + w*w);
+  lastSpeedSet=setned;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::SetVdownFpsIC(double tt) {
+  vdown=tt;
+  calcUVWfromNED();
+  vt=sqrt(u*u + v*v + w*w);
+  SetClimbRateFpsIC(-1*vdown);
+  lastSpeedSet=setned;
+}
+
+//******************************************************************************
+
+bool FGInitialCondition::getMachFromVcas(double *Mach,double vcas) {
+
+  bool result=false;
+  double guess=1.5;
+  xlo=xhi=0;
+  xmin=0;xmax=50;
+  sfunc=&FGInitialCondition::calcVcas;
+  if(findInterval(vcas,guess)) {
+    if(solve(&mach,vcas))
+      result=true;
+  }
+  return result;
+}
+
+//******************************************************************************
+
+bool FGInitialCondition::getAlpha(void) {
+  bool result=false;
+  double guess=theta-gamma;
+
+  if(vt < 0.01) return 0;
+
+  xlo=xhi=0;
+  xmin=fdmex->GetAerodynamics()->GetAlphaCLMin();
+  xmax=fdmex->GetAerodynamics()->GetAlphaCLMax();
+  sfunc=&FGInitialCondition::GammaEqOfAlpha;
+  if(findInterval(0,guess)){
+    if(solve(&alpha,0)){
+      result=true;
+      salpha=sin(alpha);
+      calpha=cos(alpha);
+    }
+  }
+  calcWindUVW();
+  return result;
+}
+
+//******************************************************************************
+
+bool FGInitialCondition::getTheta(void) {
+  bool result=false;
+  double guess=alpha+gamma;
+
+  if(vt < 0.01) return 0;
+
+  xlo=xhi=0;
+  xmin=-89;xmax=89;
+  sfunc=&FGInitialCondition::GammaEqOfTheta;
+  if(findInterval(0,guess)){
+    if(solve(&theta,0)){
+      result=true;
+      stheta=sin(theta);
+      ctheta=cos(theta);
+    }
+  }
+  calcWindUVW();
+  return result;
+}
+
+//******************************************************************************
+
+double FGInitialCondition::GammaEqOfTheta(double Theta) {
+  double a,b,c;
+  double sTheta,cTheta;
+
+  //theta=Theta; stheta=sin(theta); ctheta=cos(theta);
+  sTheta=sin(Theta); cTheta=cos(Theta);
+  calcWindUVW();
+  a=wdown + vt*calpha*cbeta + uw;
+  b=vt*sphi*sbeta + vw*sphi;
+  c=vt*cphi*salpha*cbeta + ww*cphi;
+  return vt*sgamma - ( a*sTheta - (b+c)*cTheta);
+}
+
+//******************************************************************************
+
+double FGInitialCondition::GammaEqOfAlpha(double Alpha) {
+  double a,b,c;
+  double sAlpha,cAlpha;
+  sAlpha=sin(Alpha); cAlpha=cos(Alpha);
+  a=wdown + vt*cAlpha*cbeta + uw;
+  b=vt*sphi*sbeta + vw*sphi;
+  c=vt*cphi*sAlpha*cbeta + ww*cphi;
+
+  return vt*sgamma - ( a*stheta - (b+c)*ctheta );
+}
+
+//******************************************************************************
+
+double FGInitialCondition::calcVcas(double Mach) {
+
+  double p=fdmex->GetAtmosphere()->GetPressure();
+  double psl=fdmex->GetAtmosphere()->GetPressureSL();
+  double rhosl=fdmex->GetAtmosphere()->GetDensitySL();
+  double pt,A,B,D,vcas;
+  if(Mach < 0) Mach=0;
+  if(Mach < 1)    //calculate total pressure assuming isentropic flow
+    pt=p*pow((1 + 0.2*Mach*Mach),3.5);
+  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
+
+
+    //the normal shock assumption should not be a bad one -- most supersonic
+    //aircraft place the pitot probe out front so that it is the forward
+    //most point on the aircraft.  The real shock would, of course, take
+    //on something like the shape of a rounded-off cone but, here again,
+    //the assumption should be good since the opening of the pitot probe
+    //is very small and, therefore, the effects of the shock curvature
+    //should be small as well. AFAIK, this approach is fairly well accepted
+    //within the aerospace community
+
+    B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8);
+
+    // The denominator above is zero for Mach ~ 0.38, for which
+    // we'll never be here, so we're safe
+
+    D = (2.8*Mach*Mach-0.4)*0.4167;
+    pt = p*pow(B,3.5)*D;
+  }
+
+  A = pow(((pt-p)/psl+1),0.28571);
+  vcas = sqrt(7*psl/rhosl*(A-1));
+  //cout << "calcVcas: vcas= " << vcas*fpstokts << " mach= " << Mach << " pressure: " << pt << endl;
+  return vcas;
+}
+
+//******************************************************************************
+
+bool FGInitialCondition::findInterval(double x,double guess) {
+  //void find_interval(inter_params &ip,eqfunc f,double y,double constant, int &flag){
+
+  int i=0;
+  bool found=false;
+  double flo,fhi,fguess;
+  double lo,hi,step;
+  step=0.1;
+  fguess=(this->*sfunc)(guess)-x;
+  lo=hi=guess;
+  do {
+    step=2*step;
+    lo-=step;
+    hi+=step;
+    if(lo < xmin) lo=xmin;
+    if(hi > xmax) hi=xmax;
+    i++;
+    flo=(this->*sfunc)(lo)-x;
+    fhi=(this->*sfunc)(hi)-x;
+    if(flo*fhi <=0) {  //found interval with root
+      found=true;
+      if(flo*fguess <= 0) {  //narrow interval down a bit
+        hi=lo+step;    //to pass solver interval that is as
+        //small as possible
+      }
+      else if(fhi*fguess <= 0) {
+        lo=hi-step;
+      }
+    }
+    //cout << "findInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl;
+  }
+  while((found == 0) && (i <= 100));
+  xlo=lo;
+  xhi=hi;
+  return found;
+}
+
+//******************************************************************************
+
+bool FGInitialCondition::solve(double *y,double x)
+{
+  double x1,x2,x3,f1,f2,f3,d,d0;
+  double eps=1E-5;
+  double const relax =0.9;
+  int i;
+  bool success=false;
+
+  //initializations
+  d=1;
+  x2 = 0;
+  x1=xlo;x3=xhi;
+  f1=(this->*sfunc)(x1)-x;
+  f3=(this->*sfunc)(x3)-x;
+  d0=fabs(x3-x1);
+
+  //iterations
+  i=0;
+  while ((fabs(d) > eps) && (i < 100)) {
+    d=(x3-x1)/d0;
+    x2 = x1-d*d0*f1/(f3-f1);
+
+    f2=(this->*sfunc)(x2)-x;
+    //cout << "solve x1,x2,x3: " << x1 << "," << x2 << "," << x3 << endl;
+    //cout << "                " << f1 << "," << f2 << "," << f3 << endl;
+
+    if(fabs(f2) <= 0.001) {
+      x1=x3=x2;
+    } else if(f1*f2 <= 0.0) {
+      x3=x2;
+      f3=f2;
+      f1=relax*f1;
+    } else if(f2*f3 <= 0) {
+      x1=x2;
+      f1=f2;
+      f3=relax*f3;
+    }
+    //cout << i << endl;
+    i++;
+  }//end while
+  if(i < 100) {
+    success=true;
+    *y=x2;
+  }
+
+  //cout << "Success= " << success << " Vcas: " << vcas*fpstokts << " Mach: " << x2 << endl;
+  return success;
+}
+
+//******************************************************************************
+
+double FGInitialCondition::GetWindDirDegIC(void) {
+  if(weast != 0.0)
+    return atan2(weast,wnorth)*radtodeg;
+  else if(wnorth > 0)
+    return 0.0;
+  else
+    return 180.0;
+}
+
+//******************************************************************************
+
+bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
+{
+  string resetDef, acpath;
+  ifstream initialization_file;
+  FGXMLParse initialization_file_parser;
+  Element *document, *el;
+  int n;
+
+  string sep = "/";
+# ifdef macintosh
+   string sep = ";";
+# endif
+
+  if( useStoredPath ) {
+    acpath = fdmex->GetAircraftPath() + sep + fdmex->GetModelName();
+    resetDef = acpath + sep + rstfile + ".xml";
+  } else {
+    resetDef = rstfile;
+  }
+
+  initialization_file.open(resetDef.c_str());
+  if ( !initialization_file.is_open()) {
+    cerr << "Could not open initialization file: " << resetDef << endl;
+    return false;
+  }
+
+  readXML(initialization_file, initialization_file_parser);
+  document = initialization_file_parser.GetDocument(); // document holds the
+                                                       // initialization description
+  if (document->GetName() != string("initialize")) {
+    cerr << "File: " << resetDef << " is not a reset file" << endl;
+    exit(-1);
+  }
+
+  if (document->FindElement("ubody"))
+    SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC"));
+  if (document->FindElement("vbody"))
+    SetVBodyFpsIC(document->FindElementValueAsNumberConvertTo("vbody", "FT/SEC"));
+  if (document->FindElement("wbody"))
+    SetWBodyFpsIC(document->FindElementValueAsNumberConvertTo("wbody", "FT/SEC"));
+  if (document->FindElement("latitude"))
+    SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
+  if (document->FindElement("longitude"))
+    SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG"));
+  if (document->FindElement("phi"))
+    SetRollAngleDegIC(document->FindElementValueAsNumberConvertTo("phi", "DEG"));
+  if (document->FindElement("theta"))
+    SetPitchAngleDegIC(document->FindElementValueAsNumberConvertTo("theta", "DEG"));
+  if (document->FindElement("psi"))
+    SetTrueHeadingDegIC(document->FindElementValueAsNumberConvertTo("psi", "DEG"));
+  if (document->FindElement("alpha"))
+    SetAlphaDegIC(document->FindElementValueAsNumberConvertTo("alpha", "DEG"));
+  if (document->FindElement("beta"))
+    SetBetaDegIC(document->FindElementValueAsNumberConvertTo("beta", "DEG"));
+  if (document->FindElement("gamma"))
+    SetFlightPathAngleDegIC(document->FindElementValueAsNumberConvertTo("gamma", "DEG"));
+  if (document->FindElement("roc"))
+    SetClimbRateFpmIC(document->FindElementValueAsNumberConvertTo("roc", "FT/SEC"));
+  if (document->FindElement("altitude"))
+    SetAltitudeFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT"));
+  if (document->FindElement("winddir"))
+    SetWindDirDegIC(document->FindElementValueAsNumberConvertTo("winddir", "DEG"));
+  if (document->FindElement("vwind"))
+    SetWindMagKtsIC(document->FindElementValueAsNumberConvertTo("vwind", "FT/SEC"));
+  if (document->FindElement("hwind"))
+    SetHeadWindKtsIC(document->FindElementValueAsNumberConvertTo("hwind", "KTS"));
+  if (document->FindElement("xwind"))
+    SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS"));
+  if (document->FindElement("vc"))
+    SetVcalibratedKtsIC(document->FindElementValueAsNumberConvertTo("vc", "FT/SEC"));
+  if (document->FindElement("mach"))
+    SetMachIC(document->FindElementValueAsNumber("mach"));
+  if (document->FindElement("vground"))
+    SetVgroundKtsIC(document->FindElementValueAsNumberConvertTo("vground", "FT/SEC"));
+  if (document->FindElement("running")) {
+    n = document->FindElementValueAsNumber("running");
+    if (n != 0) {
+      FGPropulsion* propulsion = fdmex->GetPropulsion();
+      for(int i=0; i<propulsion->GetNumEngines(); i++) {
+         propulsion->GetEngine(i)->SetRunning(true);
+      }
+    }
+  }
+
+  fdmex->RunIC();
+
+  return true;
+}
+
+//******************************************************************************
+
+void FGInitialCondition::bind(void){
+  PropertyManager->Tie("ic/vc-kts", this,
+                       &FGInitialCondition::GetVcalibratedKtsIC,
+                       &FGInitialCondition::SetVcalibratedKtsIC,
+                       true);
+  PropertyManager->Tie("ic/ve-kts", this,
+                       &FGInitialCondition::GetVequivalentKtsIC,
+                       &FGInitialCondition::SetVequivalentKtsIC,
+                       true);
+  PropertyManager->Tie("ic/vg-kts", this,
+                       &FGInitialCondition::GetVgroundKtsIC,
+                       &FGInitialCondition::SetVgroundKtsIC,
+                       true);
+  PropertyManager->Tie("ic/vt-kts", this,
+                       &FGInitialCondition::GetVtrueKtsIC,
+                       &FGInitialCondition::SetVtrueKtsIC,
+                       true);
+  PropertyManager->Tie("ic/mach-norm", this,
+                       &FGInitialCondition::GetMachIC,
+                       &FGInitialCondition::SetMachIC,
+                       true);
+  PropertyManager->Tie("ic/roc-fpm", this,
+                       &FGInitialCondition::GetClimbRateFpmIC,
+                       &FGInitialCondition::SetClimbRateFpmIC,
+                       true);
+  PropertyManager->Tie("ic/gamma-deg", this,
+                       &FGInitialCondition::GetFlightPathAngleDegIC,
+                       &FGInitialCondition::SetFlightPathAngleDegIC,
+                       true);
+  PropertyManager->Tie("ic/alpha-deg", this,
+                       &FGInitialCondition::GetAlphaDegIC,
+                       &FGInitialCondition::SetAlphaDegIC,
+                       true);
+  PropertyManager->Tie("ic/beta-deg", this,
+                       &FGInitialCondition::GetBetaDegIC,
+                       &FGInitialCondition::SetBetaDegIC,
+                       true);
+  PropertyManager->Tie("ic/theta-deg", this,
+                       &FGInitialCondition::GetPitchAngleDegIC,
+                       &FGInitialCondition::SetPitchAngleDegIC,
+                       true);
+  PropertyManager->Tie("ic/phi-deg", this,
+                       &FGInitialCondition::GetRollAngleDegIC,
+                       &FGInitialCondition::SetRollAngleDegIC,
+                       true);
+  PropertyManager->Tie("ic/psi-true-deg", this,
+                       &FGInitialCondition::GetHeadingDegIC );
+  PropertyManager->Tie("ic/lat-gc-deg", this,
+                       &FGInitialCondition::GetLatitudeDegIC,
+                       &FGInitialCondition::SetLatitudeDegIC,
+                       true);
+  PropertyManager->Tie("ic/long-gc-deg", this,
+                       &FGInitialCondition::GetLongitudeDegIC,
+                       &FGInitialCondition::SetLongitudeDegIC,
+                       true);
+  PropertyManager->Tie("ic/h-sl-ft", this,
+                       &FGInitialCondition::GetAltitudeFtIC,
+                       &FGInitialCondition::SetAltitudeFtIC,
+                       true);
+  PropertyManager->Tie("ic/h-agl-ft", this,
+                       &FGInitialCondition::GetAltitudeAGLFtIC,
+                       &FGInitialCondition::SetAltitudeAGLFtIC,
+                       true);
+  PropertyManager->Tie("ic/sea-level-radius-ft", this,
+                       &FGInitialCondition::GetSeaLevelRadiusFtIC,
+                       &FGInitialCondition::SetSeaLevelRadiusFtIC,
+                       true);
+  PropertyManager->Tie("ic/terrain-altitude-ft", this,
+                       &FGInitialCondition::GetTerrainAltitudeFtIC,
+                       &FGInitialCondition::SetTerrainAltitudeFtIC,
+                       true);
+  PropertyManager->Tie("ic/vg-fps", this,
+                       &FGInitialCondition::GetVgroundFpsIC,
+                       &FGInitialCondition::SetVgroundFpsIC,
+                       true);
+  PropertyManager->Tie("ic/vt-fps", this,
+                       &FGInitialCondition::GetVtrueFpsIC,
+                       &FGInitialCondition::SetVtrueFpsIC,
+                       true);
+  PropertyManager->Tie("ic/vw-bx-fps", this,
+                       &FGInitialCondition::GetWindUFpsIC);
+  PropertyManager->Tie("ic/vw-by-fps", this,
+                       &FGInitialCondition::GetWindVFpsIC);
+  PropertyManager->Tie("ic/vw-bz-fps", this,
+                       &FGInitialCondition::GetWindWFpsIC);
+  PropertyManager->Tie("ic/vw-north-fps", this,
+                       &FGInitialCondition::GetWindNFpsIC);
+  PropertyManager->Tie("ic/vw-east-fps", this,
+                       &FGInitialCondition::GetWindEFpsIC);
+  PropertyManager->Tie("ic/vw-down-fps", this,
+                       &FGInitialCondition::GetWindDFpsIC);
+  PropertyManager->Tie("ic/vw-mag-fps", this,
+                       &FGInitialCondition::GetWindFpsIC);
+ /*  PropertyManager->Tie("ic/vw-dir-deg", this,
+                       &FGInitialCondition::GetWindDirDegIC,
+                       &FGInitialCondition::SetWindDirDegIC,
+                       true); */
+
+  PropertyManager->Tie("ic/roc-fps", this,
+                       &FGInitialCondition::GetClimbRateFpsIC,
+                       &FGInitialCondition::SetClimbRateFpsIC,
+                       true);
+  /* PropertyManager->Tie("ic/u-fps", this,
+                       &FGInitialCondition::GetUBodyFpsIC,
+                       &FGInitialCondition::SetUBodyFpsIC,
+                       true);
+  PropertyManager->Tie("ic/v-fps", this,
+                       &FGInitialCondition::GetVBodyFpsIC,
+                       &FGInitialCondition::SetVBodyFpsIC,
+                       true);
+  PropertyManager->Tie("ic/w-fps", this,
+                       &FGInitialCondition::GetWBodyFpsIC,
+                       &FGInitialCondition::SetWBodyFpsIC,
+                       true); */
+
+  PropertyManager->Tie("ic/gamma-rad", this,
+                       &FGInitialCondition::GetFlightPathAngleRadIC,
+                       &FGInitialCondition::SetFlightPathAngleRadIC,
+                       true);
+  PropertyManager->Tie("ic/alpha-rad", this,
+                       &FGInitialCondition::GetAlphaRadIC,
+                       &FGInitialCondition::SetAlphaRadIC,
+                       true);
+  PropertyManager->Tie("ic/theta-rad", this,
+                       &FGInitialCondition::GetPitchAngleRadIC,
+                       &FGInitialCondition::SetPitchAngleRadIC,
+                       true);
+  PropertyManager->Tie("ic/beta-rad", this,
+                       &FGInitialCondition::GetBetaRadIC,
+                       &FGInitialCondition::SetBetaRadIC,
+                       true);
+  PropertyManager->Tie("ic/phi-rad", this,
+                       &FGInitialCondition::GetRollAngleRadIC,
+                       &FGInitialCondition::SetRollAngleRadIC,
+                       true);
+  PropertyManager->Tie("ic/psi-true-rad", this,
+                       &FGInitialCondition::GetHeadingRadIC);
+  PropertyManager->Tie("ic/lat-gc-rad", this,
+                       &FGInitialCondition::GetLatitudeRadIC,
+                       &FGInitialCondition::SetLatitudeRadIC,
+                       true);
+  PropertyManager->Tie("ic/long-gc-rad", this,
+                       &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);
+
+}
+
+//******************************************************************************
+
+void FGInitialCondition::unbind(void){
+  PropertyManager->Untie("ic/vc-kts");
+  PropertyManager->Untie("ic/ve-kts");
+  PropertyManager->Untie("ic/vg-kts");
+  PropertyManager->Untie("ic/vt-kts");
+  PropertyManager->Untie("ic/mach-norm");
+  PropertyManager->Untie("ic/roc-fpm");
+  PropertyManager->Untie("ic/gamma-deg");
+  PropertyManager->Untie("ic/alpha-deg");
+  PropertyManager->Untie("ic/beta-deg");
+  PropertyManager->Untie("ic/theta-deg");
+  PropertyManager->Untie("ic/phi-deg");
+  PropertyManager->Untie("ic/psi-true-deg");
+  PropertyManager->Untie("ic/lat-gc-deg");
+  PropertyManager->Untie("ic/long-gc-deg");
+  PropertyManager->Untie("ic/h-sl-ft");
+  PropertyManager->Untie("ic/h-agl-ft");
+  PropertyManager->Untie("ic/sea-level-radius-ft");
+  PropertyManager->Untie("ic/terrain-altitude-ft");
+  PropertyManager->Untie("ic/vg-fps");
+  PropertyManager->Untie("ic/vt-fps");
+  PropertyManager->Untie("ic/vw-bx-fps");
+  PropertyManager->Untie("ic/vw-by-fps");
+  PropertyManager->Untie("ic/vw-bz-fps");
+  PropertyManager->Untie("ic/vw-north-fps");
+  PropertyManager->Untie("ic/vw-east-fps");
+  PropertyManager->Untie("ic/vw-down-fps");
+  PropertyManager->Untie("ic/vw-mag-fps");
+  /* PropertyManager->Untie("ic/vw-dir-deg"); */
+
+  PropertyManager->Untie("ic/roc-fps");
+
+  /*  PropertyManager->Untie("ic/u-fps");
+  PropertyManager->Untie("ic/v-fps");
+  PropertyManager->Untie("ic/w-fps"); */
+
+  PropertyManager->Untie("ic/gamma-rad");
+  PropertyManager->Untie("ic/alpha-rad");
+  PropertyManager->Untie("ic/theta-rad");
+  PropertyManager->Untie("ic/beta-rad");
+  PropertyManager->Untie("ic/phi-rad");
+  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");
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGInitialCondition::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: FGInitialCondition" << endl;
+    if (from == 1) cout << "Destroyed:    FGInitialCondition" << 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/initialization/FGInitialCondition.h b/src/FDM/JSBSim/initialization/FGInitialCondition.h
new file mode 100644 (file)
index 0000000..b11c9ce
--- /dev/null
@@ -0,0 +1,328 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGInitialCondition.h
+ Author:       Tony Peden
+ Date started: 7/1/99
+
+ ------------- 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/1/99   TP   Created
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+The purpose of this class is to take a set of initial conditions and provide
+a kinematically consistent set of body axis velocity components, euler
+angles, and altitude.  This class does not attempt to trim the model i.e.
+the sim will most likely start in a very dynamic state (unless, of course,
+you have chosen your IC's wisely) even after setting it up with this class.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGINITIALCONDITION_H
+#define FGINITIALCONDITION_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <FGFDMExec.h>
+#include <FGJSBBase.h>
+#include <math/FGColumnVector3.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_INITIALCONDITION "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset;
+typedef enum { setwned, setwmd, setwhc } windset;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Takes a set of initial conditions and provide a kinematically consistent set
+    of body axis velocity components, euler angles, and altitude.  This class
+    does not attempt to trim the model i.e. the sim will most likely start in a
+    very dynamic state (unless, of course, you have chosen your IC's wisely)
+    even after setting it up with this class.
+
+   USAGE NOTES
+
+   With a valid object of FGFDMExec and an aircraft model loaded
+   FGInitialCondition fgic=new FGInitialCondition(FDMExec);
+   fgic->SetVcalibratedKtsIC()
+   fgic->SetAltitudeFtIC();
+
+   //to directly into Run
+   FDMExec->GetState()->Initialize(fgic)
+   delete fgic;
+   FDMExec->Run()
+
+   //or to loop the sim w/o integrating
+   FDMExec->RunIC(fgic)
+
+   Speed:
+
+   Since vc, ve, vt, and mach all represent speed, the remaining
+   three are recalculated each time one of them is set (using the
+   current altitude).  The most recent speed set is remembered so
+   that if and when altitude is reset, the last set speed is used
+   to recalculate the remaining three. Setting any of the body
+   components forces a recalculation of vt and vt then becomes the
+   most recent speed set.
+
+   Alpha,Gamma, and Theta:
+
+   This class assumes that it will be used to set up the sim for a
+   steady, zero pitch rate condition. Since any two of those angles
+   specifies the third gamma (flight path angle) is favored when setting
+   alpha and theta and alpha is favored when setting gamma. i.e.
+
+   - set alpha : recalculate theta using gamma as currently set
+   - set theta : recalculate alpha using gamma as currently set
+   - set gamma : recalculate theta using alpha as currently set
+
+   The idea being that gamma is most interesting to pilots (since it
+   is indicative of climb rate).
+
+   Setting climb rate is, for the purpose of this discussion,
+   considered equivalent to setting gamma.
+
+   These are the items that can be set in an initialization file:
+
+   UBODY <velocity, ft/sec>
+   VBODY <velocity, ft/sec>
+   WBODY <velocity, ft/sec>
+   LATITUDE <position, degrees>
+   LONGITUDE <position, degrees>
+   PHI <orientation, degrees>
+   THETA <orientation, degrees>
+   PSI <orientation, degrees>
+   ALPHA <angle, degrees>
+   BETA <angle, degrees>
+   GAMMA <angle, degrees>
+   ROC <vertical velocity, ft/sec>
+   ALTITUDE <altitude, ft>
+   WINDDIR <wind from-angle, degrees>
+   VWIND <magnitude wind speed, ft/sec>
+   HWIND <headwind speed, knots>
+   XWIND <crosswind speed, knots>
+   VC <calibrated airspeed, ft/sec>
+   MACH <mach>
+   VGROUND <ground speed, ft/sec>
+   RUNNING <0 or 1>
+
+
+   @author Tony Peden
+   @version "$Id$"
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGInitialCondition : public FGJSBBase
+{
+public:
+  /// Constructor
+  FGInitialCondition(FGFDMExec *fdmex);
+  /// Destructor
+  ~FGInitialCondition();
+
+  void SetVcalibratedKtsIC(double tt);
+  void SetVequivalentKtsIC(double tt);
+  inline void SetVtrueKtsIC(double tt)   { SetVtrueFpsIC(tt*ktstofps);   }
+  inline void SetVgroundKtsIC(double tt) { SetVgroundFpsIC(tt*ktstofps); }
+  void SetMachIC(double tt);
+
+  inline void SetAlphaDegIC(double tt)      { SetAlphaRadIC(tt*degtorad); }
+  inline void SetBetaDegIC(double tt)       { SetBetaRadIC(tt*degtorad);}
+
+  inline void SetPitchAngleDegIC(double tt) { SetPitchAngleRadIC(tt*degtorad); }
+  inline void SetRollAngleDegIC(double tt)  { SetRollAngleRadIC(tt*degtorad);}
+  inline void SetTrueHeadingDegIC(double tt){ SetTrueHeadingRadIC(tt*degtorad); }
+
+  void SetClimbRateFpmIC(double tt);
+  inline void SetFlightPathAngleDegIC(double tt) { SetFlightPathAngleRadIC(tt*degtorad); }
+
+  void SetAltitudeFtIC(double tt);
+  void SetAltitudeAGLFtIC(double tt);
+
+  void SetSeaLevelRadiusFtIC(double tt);
+  void SetTerrainAltitudeFtIC(double tt);
+
+  inline void SetLatitudeDegIC(double tt)  { latitude=tt*degtorad; }
+  inline void SetLongitudeDegIC(double tt) { longitude=tt*degtorad; }
+
+
+  inline double GetVcalibratedKtsIC(void) const { return vc*fpstokts; }
+  inline double GetVequivalentKtsIC(void) const { return ve*fpstokts; }
+  inline double GetVgroundKtsIC(void) const { return vg*fpstokts; }
+  inline double GetVtrueKtsIC(void) const { return vt*fpstokts; }
+  inline double GetMachIC(void) const { return mach; }
+
+  inline double GetClimbRateFpmIC(void) const { return hdot*60; }
+  inline double GetFlightPathAngleDegIC(void)const  { return gamma*radtodeg; }
+
+  inline double GetAlphaDegIC(void) const { return alpha*radtodeg; }
+  inline double GetBetaDegIC(void) const  { return beta*radtodeg; }
+
+  inline double GetPitchAngleDegIC(void) const { return theta*radtodeg; }
+  inline double GetRollAngleDegIC(void) const { return phi*radtodeg; }
+  inline double GetHeadingDegIC(void) const { return psi*radtodeg; }
+
+  inline double GetLatitudeDegIC(void) const { return latitude*radtodeg; }
+  inline double GetLongitudeDegIC(void) const { return longitude*radtodeg; }
+
+  inline double GetAltitudeFtIC(void) const { return altitude; }
+  inline double GetAltitudeAGLFtIC(void) const { return altitude - terrain_altitude; }
+
+  inline double GetSeaLevelRadiusFtIC(void) const { return sea_level_radius; }
+  inline double GetTerrainAltitudeFtIC(void) const { return terrain_altitude; }
+
+  void SetVgroundFpsIC(double tt);
+  void SetVtrueFpsIC(double tt);
+  void SetUBodyFpsIC(double tt);
+  void SetVBodyFpsIC(double tt);
+  void SetWBodyFpsIC(double tt);
+  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);
+
+  void SetWindMagKtsIC(double mag);
+  void SetWindDirDegIC(double dir);
+
+  void SetHeadWindKtsIC(double head);
+  void SetCrossWindKtsIC(double cross);// positive from left
+
+  void SetWindDownKtsIC(double wD);
+
+  void SetClimbRateFpsIC(double tt);
+  inline double GetVgroundFpsIC(void) const  { return vg; }
+  inline double GetVtrueFpsIC(void) const { return vt; }
+  inline double GetWindUFpsIC(void) const { return uw; }
+  inline double GetWindVFpsIC(void) const { return vw; }
+  inline double GetWindWFpsIC(void) const { return ww; }
+  inline double GetWindNFpsIC(void) const { return wnorth; }
+  inline double GetWindEFpsIC(void) const { return weast; }
+  inline double GetWindDFpsIC(void) const { return wdown; }
+  inline double GetWindFpsIC(void)  const { return sqrt(wnorth*wnorth + weast*weast); }
+  double GetWindDirDegIC(void);
+  inline double GetClimbRateFpsIC(void) const { return hdot; }
+  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);
+  void SetBetaRadIC(double tt);
+  void SetRollAngleRadIC(double tt);
+  void SetTrueHeadingRadIC(double tt);
+  inline void SetLatitudeRadIC(double tt) { latitude=tt; }
+  inline void SetLongitudeRadIC(double tt) { longitude=tt; }
+  inline double GetFlightPathAngleRadIC(void) const { return gamma; }
+  inline double GetAlphaRadIC(void) const      { return alpha; }
+  inline double GetPitchAngleRadIC(void) const { return theta; }
+  inline double GetBetaRadIC(void) const       { return beta; }
+  inline double GetRollAngleRadIC(void) const  { return phi; }
+  inline double GetHeadingRadIC(void) const   { return psi; }
+  inline double GetLatitudeRadIC(void) const { return latitude; }
+  inline double GetLongitudeRadIC(void) const { return longitude; }
+  inline double GetThetaRadIC(void) const { return theta; }
+  inline double GetPhiRadIC(void)  const  { return phi; }
+  inline double GetPsiRadIC(void) const   { return psi; }
+
+  inline speedset GetSpeedSet(void) { return lastSpeedSet; }
+  inline windset GetWindSet(void) { return lastWindSet; }
+
+  bool Load(string rstname, bool useStoredPath = true );
+
+  void bind(void);
+  void unbind(void);
+
+
+private:
+  double vt,vc,ve,vg;
+  double mach;
+  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;
+  double whead, wcross, wdir, wmag;
+  double sea_level_radius;
+  double terrain_altitude;
+  double radius_to_vehicle;
+
+  double  alpha, beta, theta, phi, psi, gamma;
+  double salpha,sbeta,stheta,sphi,spsi,sgamma;
+  double calpha,cbeta,ctheta,cphi,cpsi,cgamma;
+
+  double xlo, xhi,xmin,xmax;
+
+  typedef double (FGInitialCondition::*fp)(double x);
+  fp sfunc;
+
+  speedset lastSpeedSet;
+  windset lastWindSet;
+
+  FGFDMExec *fdmex;
+  FGPropertyManager *PropertyManager;
+
+  bool getAlpha(void);
+  bool getTheta(void);
+  bool getMachFromVcas(double *Mach,double vcas);
+
+  double GammaEqOfTheta(double Theta);
+  double GammaEqOfAlpha(double Alpha);
+  double calcVcas(double Mach);
+  void calcUVWfromNED(void);
+  void calcWindUVW(void);
+
+  bool findInterval(double x,double guess);
+  bool solve(double *y, double x);
+  void Debug(int from);
+};
+}
+#endif
+
diff --git a/src/FDM/JSBSim/initialization/FGTrim.cpp b/src/FDM/JSBSim/initialization/FGTrim.cpp
new file mode 100644 (file)
index 0000000..26edd99
--- /dev/null
@@ -0,0 +1,683 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGTrim.cpp
+ Author:       Tony Peden
+ Date started: 9/8/99
+ --------- 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
+--------------------------------------------------------------------------------
+9/8/99   TP   Created
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+This class takes the given set of IC's and finds the angle of attack, elevator,
+and throttle setting required to fly steady level. This is currently for in-air
+conditions only.  It is implemented using an iterative, one-axis-at-a-time
+scheme. */
+
+//  !!!!!!! BEWARE ALL YE WHO ENTER HERE !!!!!!!
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <stdlib.h>
+
+#include <FGFDMExec.h>
+#include <models/FGAtmosphere.h>
+#include "FGInitialCondition.h"
+#include "FGTrim.h"
+#include <models/FGAircraft.h>
+#include <models/FGMassBalance.h>
+#include <models/FGGroundReactions.h>
+#include <models/FGInertial.h>
+#include <models/FGAerodynamics.h>
+#include <math/FGColumnVector3.h>
+
+#if _MSC_VER
+#pragma warning (disable : 4786 4788)
+#endif
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_TRIM;
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTrim::FGTrim(FGFDMExec *FDMExec,TrimMode tt) {
+
+  N=Nsub=0;
+  max_iterations=60;
+  max_sub_iterations=100;
+  Tolerance=1E-3;
+  A_Tolerance = Tolerance / 10;
+  
+  Debug=0;DebugLevel=0;
+  fdmex=FDMExec;
+  fgic=fdmex->GetIC();
+  total_its=0;
+  trimudot=true;
+  gamma_fallback=true;
+  axis_count=0;
+  mode=tt;
+  xlo=xhi=alo=ahi=0.0;
+  targetNlf=1.0;
+  debug_axis=tAll;
+  SetMode(tt);
+  if (debug_lvl & 2) cout << "Instantiated: FGTrim" << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTrim::~FGTrim(void) {
+  for(current_axis=0; current_axis<TrimAxes.size(); current_axis++) {
+    delete TrimAxes[current_axis];
+  }
+  delete[] sub_iterations;
+  delete[] successful;
+  delete[] solution;
+  if (debug_lvl & 2) cout << "Destroyed:    FGTrim" << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::TrimStats() {
+  char out[80];
+  int run_sum=0;
+  cout << endl << "  Trim Statistics: " << endl;
+  cout << "    Total Iterations: " << total_its << endl;
+  if(total_its > 0) {
+    cout << "    Sub-iterations:" << endl;
+    for(current_axis=0; current_axis<TrimAxes.size(); current_axis++) {
+      run_sum+=TrimAxes[current_axis]->GetRunCount();
+      snprintf(out,80,"   %5s: %3.0f average: %5.2f  successful: %3.0f  stability: %5.2f\n",
+                  TrimAxes[current_axis]->GetStateName().c_str(),
+                  sub_iterations[current_axis],
+                  sub_iterations[current_axis]/double(total_its),
+                  successful[current_axis],
+                  TrimAxes[current_axis]->GetAvgStability() );
+      cout << out;
+    }
+    cout << "    Run Count: " << run_sum << endl;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::Report(void) {
+  cout << "  Trim Results: " << endl;
+  for(current_axis=0; current_axis<TrimAxes.size(); current_axis++)
+    TrimAxes[current_axis]->AxisReport();
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::ClearStates(void) {
+    FGTrimAxis* ta;
+    
+    mode=tCustom;
+    vector<FGTrimAxis*>::iterator iAxes;
+    iAxes = TrimAxes.begin();
+    while (iAxes != TrimAxes.end()) {
+      ta=*iAxes;
+      delete ta;
+      iAxes++;
+    }
+    TrimAxes.clear();
+    //cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
+}
+    
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGTrim::AddState( State state, Control control ) {
+  FGTrimAxis* ta;
+  bool result=true;
+  
+  mode = tCustom;
+  vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
+  while (iAxes != TrimAxes.end()) {
+      ta=*iAxes;
+      if( ta->GetStateType() == state )
+        result=false;
+      iAxes++;
+  }
+  if(result) {
+    TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,state,control));
+    delete[] sub_iterations;
+    delete[] successful;
+    delete[] solution;
+    sub_iterations=new double[TrimAxes.size()];
+    successful=new double[TrimAxes.size()];
+    solution=new bool[TrimAxes.size()];
+  }
+  return result;
+}  
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGTrim::RemoveState( State state ) {
+  FGTrimAxis* ta;
+  bool result=false;
+  
+  mode = tCustom;
+  vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
+  while (iAxes != TrimAxes.end()) {
+      ta=*iAxes;
+      if( ta->GetStateType() == state ) {
+        delete ta;
+        TrimAxes.erase(iAxes);
+        result=true;
+        continue;
+      }
+      iAxes++;
+  }
+  if(result) {
+    delete[] sub_iterations;
+    delete[] successful;
+    delete[] solution;
+    sub_iterations=new double[TrimAxes.size()];
+    successful=new double[TrimAxes.size()];
+    solution=new bool[TrimAxes.size()];
+  }  
+  return result;
+}  
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGTrim::EditState( State state, Control new_control ){       
+  FGTrimAxis* ta;
+  bool result=false;
+  
+  mode = tCustom;
+  vector <FGTrimAxis*>::iterator iAxes = TrimAxes.begin();
+  while (iAxes != TrimAxes.end()) {
+      ta=*iAxes;
+      if( ta->GetStateType() == state ) {
+        TrimAxes.insert(iAxes,1,new FGTrimAxis(fdmex,fgic,state,new_control));
+        delete ta;
+        TrimAxes.erase(iAxes+1);
+        result=true;
+        break;
+      }
+      iAxes++;
+  }
+  return result;
+}  
+       
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGTrim::DoTrim(void) {
+  
+  trim_failed=false;
+  int i;
+
+  for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
+    fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(false);
+  }
+
+  fdmex->DisableOutput();
+  
+  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++) {
+    //cout << current_axis << "  " << TrimAxes[current_axis]->GetStateName()
+    //<< "  " << TrimAxes[current_axis]->GetControlName()<< endl;
+    if(TrimAxes[current_axis]->GetStateType() == tQdot) {
+      if(mode == tGround) {
+         TrimAxes[current_axis]->initTheta();
+      }  
+    }  
+    xlo=TrimAxes[current_axis]->GetControlMin();
+    xhi=TrimAxes[current_axis]->GetControlMax();
+    TrimAxes[current_axis]->SetControl((xlo+xhi)/2);
+    TrimAxes[current_axis]->Run();
+    //TrimAxes[current_axis]->AxisReport();
+    sub_iterations[current_axis]=0;
+    successful[current_axis]=0;
+    solution[current_axis]=false;
+  }
+  
+  
+  if(mode == tPullup ) {
+    cout << "Setting pitch rate and nlf... " << endl;
+    setupPullup();
+    cout << "pitch rate done ... " << endl;
+    TrimAxes[0]->SetStateTarget(targetNlf);
+    cout << "nlf done" << endl;
+  } else if (mode == tTurn) {
+    setupTurn();
+    //TrimAxes[0]->SetStateTarget(targetNlf);
+  }  
+  
+  do {
+    axis_count=0;
+    for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
+      setDebug();
+      updateRates();
+      Nsub=0;
+      if(!solution[current_axis]) {
+        if(checkLimits()) { 
+          solution[current_axis]=true;
+          solve();
+        }  
+      } else if(findInterval()) {
+        solve();
+      } else {
+        solution[current_axis]=false;
+      }  
+      sub_iterations[current_axis]+=Nsub;
+    } 
+    for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
+      //these checks need to be done after all the axes have run
+      if(Debug > 0) TrimAxes[current_axis]->AxisReport();
+      if(TrimAxes[current_axis]->InTolerance()) {
+        axis_count++;
+        successful[current_axis]++;
+      } 
+    }
+    
+
+    if((axis_count == TrimAxes.size()-1) && (TrimAxes.size() > 1)) {
+      //cout << TrimAxes.size()-1 << " out of " << TrimAxes.size() << "!" << endl;
+      //At this point we can check the input limits of the failed axis
+      //and declare the trim failed if there is no sign change. If there
+      //is, keep going until success or max iteration count
+
+      //Oh, well: two out of three ain't bad
+      for(current_axis=0;current_axis<TrimAxes.size();current_axis++) {
+        //these checks need to be done after all the axes have run
+        if(!TrimAxes[current_axis]->InTolerance()) {
+          if(!checkLimits()) {
+            // special case this for now -- if other cases arise proper
+            // support can be added to FGTrimAxis
+            if( (gamma_fallback) &&
+                (TrimAxes[current_axis]->GetStateType() == tUdot) &&
+                (TrimAxes[current_axis]->GetControlType() == tThrottle)) {
+              cout << "  Can't trim udot with throttle, trying flight"
+              << " path angle. (" << N << ")" << endl;
+              if(TrimAxes[current_axis]->GetState() > 0)
+                TrimAxes[current_axis]->SetControlToMin();
+              else
+                TrimAxes[current_axis]->SetControlToMax();
+              TrimAxes[current_axis]->Run();
+              delete TrimAxes[current_axis];
+              TrimAxes[current_axis]=new FGTrimAxis(fdmex,fgic,tUdot,
+                                                    tGamma );
+            } else {
+              cout << "  Sorry, " << TrimAxes[current_axis]->GetStateName()
+              << " doesn't appear to be trimmable" << endl;
+              //total_its=k;
+              trim_failed=true; //force the trim to fail
+            } //gamma_fallback
+          }
+        } //solution check
+      } //for loop
+    } //all-but-one check
+    N++;
+    if(N > max_iterations)
+      trim_failed=true;
+  } while((axis_count < TrimAxes.size()) && (!trim_failed));
+  if((!trim_failed) && (axis_count >= TrimAxes.size())) {
+    total_its=N;
+    if (debug_lvl > 0)
+        cout << endl << "  Trim successful" << endl;
+  } else {
+    total_its=N;
+    if (debug_lvl > 0)
+        cout << endl << "  Trim failed" << endl;
+  }
+  for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
+    fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
+  }
+  fdmex->EnableOutput();
+  return !trim_failed;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGTrim::solve(void) {
+
+  double x1,x2,x3,f1,f2,f3,d,d0;
+  const double relax =0.9;
+  double eps=TrimAxes[current_axis]->GetSolverEps();
+
+  x1=x2=x3=0;
+  d=1;
+  bool success=false;
+  //initializations
+  if( solutionDomain != 0) {
+   /* if(ahi > alo) { */
+      x1=xlo;f1=alo;
+      x3=xhi;f3=ahi;
+   /* } else {
+      x1=xhi;f1=ahi;
+      x3=xlo;f3=alo;
+    }   */
+    d0=fabs(x3-x1);
+    //iterations
+    //max_sub_iterations=TrimAxes[current_axis]->GetIterationLimit();
+    while ( (TrimAxes[current_axis]->InTolerance() == false )
+             && (fabs(d) > eps) && (Nsub < max_sub_iterations)) {
+      Nsub++;
+      d=(x3-x1)/d0;
+      x2=x1-d*d0*f1/(f3-f1);
+      TrimAxes[current_axis]->SetControl(x2);
+      TrimAxes[current_axis]->Run();
+      f2=TrimAxes[current_axis]->GetState();
+      if(Debug > 1) {
+        cout << "FGTrim::solve Nsub,x1,x2,x3: " << Nsub << ", " << x1
+        << ", " << x2 << ", " << x3 << endl;
+        cout << "                             " << f1 << ", " << f2 << ", " << f3 << endl;
+      }
+      if(f1*f2 <= 0.0) {
+        x3=x2;
+        f3=f2;
+        f1=relax*f1;
+        //cout << "Solution is between x1 and x2" << endl;
+      }
+      else if(f2*f3 <= 0.0) {
+        x1=x2;
+        f1=f2;
+        f3=relax*f3;
+        //cout << "Solution is between x2 and x3" << endl;
+
+      }
+      //cout << i << endl;
+
+      
+    }//end while
+    if(Nsub < max_sub_iterations) success=true;
+  }  
+  return success;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/*
+ produces an interval (xlo..xhi) on one side or the other of the current 
+ control value in which a solution exists.  This domain is, hopefully, 
+ smaller than xmin..0 or 0..xmax and the solver will require fewer iterations 
+ to find the solution. This is, hopefully, more efficient than having the 
+ solver start from scratch every time. Maybe it isn't though...
+ This tries to take advantage of the idea that the changes from iteration to
+ iteration will be small after the first one or two top-level iterations.
+
+ assumes that changing the control will a produce significant change in the
+ accel i.e. checkLimits() has already been called.
+
+ if a solution is found above the current control, the function returns true 
+ and xlo is set to the current control, xhi to the interval max it found, and 
+ solutionDomain is set to 1.
+ if the solution lies below the current control, then the function returns 
+ true and xlo is set to the interval min it found and xmax to the current 
+ control. if no solution is found, then the function returns false.
+ in all cases, alo=accel(xlo) and ahi=accel(xhi) after the function exits.
+ no assumptions about the state of the sim after this function has run 
+ can be made.
+*/
+bool FGTrim::findInterval(void) {
+  bool found=false;
+  double step;
+  double current_control=TrimAxes[current_axis]->GetControl();
+  double current_accel=TrimAxes[current_axis]->GetState();;
+  double xmin=TrimAxes[current_axis]->GetControlMin();
+  double xmax=TrimAxes[current_axis]->GetControlMax();
+  double lastxlo,lastxhi,lastalo,lastahi;
+  
+  step=0.025*fabs(xmax);
+  xlo=xhi=current_control;
+  alo=ahi=current_accel;
+  lastxlo=xlo;lastxhi=xhi;
+  lastalo=alo;lastahi=ahi;
+  do {
+    
+    Nsub++;
+    step*=2;
+    xlo-=step;
+    if(xlo < xmin) xlo=xmin;
+    xhi+=step;
+    if(xhi > xmax) xhi=xmax;
+    TrimAxes[current_axis]->SetControl(xlo);
+    TrimAxes[current_axis]->Run();
+    alo=TrimAxes[current_axis]->GetState();
+    TrimAxes[current_axis]->SetControl(xhi);
+    TrimAxes[current_axis]->Run();
+    ahi=TrimAxes[current_axis]->GetState();
+    if(fabs(ahi-alo) <= TrimAxes[current_axis]->GetTolerance()) continue;
+    if(alo*ahi <=0) {  //found interval with root
+      found=true;
+      if(alo*current_accel <= 0) { //narrow interval down a bit
+        solutionDomain=-1;
+        xhi=lastxlo;
+        ahi=lastalo;
+        //xhi=current_control;
+        //ahi=current_accel;
+      } else {
+        solutionDomain=1;
+        xlo=lastxhi;
+        alo=lastahi;
+        //xlo=current_control;
+        //alo=current_accel;
+      }     
+    }
+    lastxlo=xlo;lastxhi=xhi;
+    lastalo=alo;lastahi=ahi;
+    if( !found && xlo==xmin && xhi==xmax ) continue;
+    if(Debug > 1)
+      cout << "FGTrim::findInterval: Nsub=" << Nsub << " Lo= " << xlo
+                           << " Hi= " << xhi << " alo*ahi: " << alo*ahi << endl;
+  } while(!found && (Nsub <= max_sub_iterations) );
+  return found;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//checks to see which side of the current control value the solution is on
+//and sets solutionDomain accordingly:
+//  1 if solution is between the current and max
+// -1 if solution is between the min and current
+//  0 if there is no solution
+// 
+//if changing the control produces no significant change in the accel then
+//solutionDomain is set to zero and the function returns false
+//if a solution is found, then xlo and xhi are set so that they bracket
+//the solution, alo is set to accel(xlo), and ahi is set to accel(xhi)
+//if there is no change or no solution then xlo=xmin, alo=accel(xmin) and
+//xhi=xmax and ahi=accel(xmax) 
+//in all cases the sim is left such that the control=xmax and accel=ahi
+
+bool FGTrim::checkLimits(void) {
+  bool solutionExists;
+  double current_control=TrimAxes[current_axis]->GetControl();
+  double current_accel=TrimAxes[current_axis]->GetState();
+  xlo=TrimAxes[current_axis]->GetControlMin();
+  xhi=TrimAxes[current_axis]->GetControlMax();
+
+  TrimAxes[current_axis]->SetControl(xlo);
+  TrimAxes[current_axis]->Run();
+  alo=TrimAxes[current_axis]->GetState();
+  TrimAxes[current_axis]->SetControl(xhi);
+  TrimAxes[current_axis]->Run();
+  ahi=TrimAxes[current_axis]->GetState();
+  if(Debug > 1)
+    cout << "checkLimits() xlo,xhi,alo,ahi: " << xlo << ", " << xhi << ", "
+                                              << alo << ", " << ahi << endl;
+  solutionDomain=0;
+  solutionExists=false;
+  if(fabs(ahi-alo) > TrimAxes[current_axis]->GetTolerance()) {
+    if(alo*current_accel <= 0) {
+      solutionExists=true;
+      solutionDomain=-1;
+      xhi=current_control;
+      ahi=current_accel;
+    } else if(current_accel*ahi < 0){
+      solutionExists=true;
+      solutionDomain=1;
+      xlo=current_control;
+      alo=current_accel;  
+    }
+  } 
+  TrimAxes[current_axis]->SetControl(current_control);
+  TrimAxes[current_axis]->Run();
+  return solutionExists;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::setupPullup() {
+  double g,q,cgamma;
+  g=fdmex->GetInertial()->gravity();
+  cgamma=cos(fgic->GetFlightPathAngleRadIC());
+  cout << "setPitchRateInPullup():  " << g << ", " << cgamma << ", "
+       << fgic->GetVtrueFpsIC() << endl;
+  q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
+  cout << targetNlf << ", " << q << endl;
+  fgic->SetQRadpsIC(q);
+  cout << "setPitchRateInPullup() complete" << endl;
+  
+}  
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::setupTurn(void){
+  double g,phi;
+  phi = fgic->GetRollAngleRadIC();
+  if( fabs(phi) > 0.001 && fabs(phi) < 1.56 ) {
+    targetNlf = 1 / cos(phi);
+    g = fdmex->GetInertial()->gravity(); 
+    psidot = g*tan(phi) / fgic->GetUBodyFpsIC();
+    cout << targetNlf << ", " << psidot << endl;
+  }
+   
+}  
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::updateRates(void){
+  if( mode == tTurn ) {
+    double phi = fgic->GetRollAngleRadIC();
+    double g = fdmex->GetInertial()->gravity(); 
+    double p,q,r,theta;
+    if(fabs(phi) > 0.001 && fabs(phi) < 1.56 ) {
+      theta=fgic->GetPitchAngleRadIC();
+      phi=fgic->GetRollAngleRadIC();
+      psidot = g*tan(phi) / fgic->GetUBodyFpsIC();
+      p=-psidot*sin(theta);
+      q=psidot*cos(theta)*sin(phi);
+      r=psidot*cos(theta)*cos(phi);
+    } else {
+      p=q=r=0;
+    }      
+    fgic->SetPRadpsIC(p);
+    fgic->SetQRadpsIC(q);
+    fgic->SetRRadpsIC(r);
+  } else if( mode == tPullup && fabs(targetNlf-1) > 0.01) {
+      double g,q,cgamma;
+      g=fdmex->GetInertial()->gravity();
+      cgamma=cos(fgic->GetFlightPathAngleRadIC());
+      q=g*(targetNlf-cgamma)/fgic->GetVtrueFpsIC();
+      fgic->SetQRadpsIC(q);
+  }  
+}  
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::setDebug(void) {
+  if(debug_axis == tAll ||
+      TrimAxes[current_axis]->GetStateType() == debug_axis ) {
+    Debug=DebugLevel; 
+    return;
+  } else {
+    Debug=0;
+    return;
+  }
+}      
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTrim::SetMode(TrimMode tt) {
+    ClearStates();
+    mode=tt;
+    switch(tt) {
+      case tFull:
+        if (debug_lvl > 0)          
+          cout << "  Full Trim" << endl;
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+        break;
+      case tLongitudinal:
+        if (debug_lvl > 0)          
+          cout << "  Longitudinal Trim" << endl;
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+        break;
+      case tGround:
+        if (debug_lvl > 0)          
+          cout << "  Ground Trim" << endl;
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAltAGL ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tTheta ));
+        //TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tPhi ));
+        break;
+      case tPullup:
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tNlf,tAlpha ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tHmgt,tBeta ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tPhi ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+        break;
+      case tTurn:
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tWdot,tAlpha ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tUdot,tThrottle ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tQdot,tPitchTrim ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tVdot,tBeta ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tPdot,tAileron ));
+        TrimAxes.push_back(new FGTrimAxis(fdmex,fgic,tRdot,tRudder ));
+        break;
+      case tCustom:
+      case tNone:
+        break;
+    }
+    //cout << "TrimAxes.size(): " << TrimAxes.size() << endl;
+    sub_iterations=new double[TrimAxes.size()];
+    successful=new double[TrimAxes.size()];
+    solution=new bool[TrimAxes.size()];
+    current_axis=0;
+}    
+//YOU WERE WARNED, BUT YOU DID IT ANYWAY.
+}
diff --git a/src/FDM/JSBSim/initialization/FGTrim.h b/src/FDM/JSBSim/initialization/FGTrim.h
new file mode 100644 (file)
index 0000000..1f6bbce
--- /dev/null
@@ -0,0 +1,295 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGTrim.h
+ Author:       Tony Peden
+ Date started: 7/1/99
+
+ ------------- 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
+--------------------------------------------------------------------------------
+9/8/99   TP   Created
+
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+This class takes the given set of IC's and finds the aircraft state required to
+maintain a specified flight condition.  This flight condition can be
+steady-level with non-zero sideslip, a steady turn, a pull-up or pushover.
+On-ground conditions can be trimmed as well, but this is currently limited to
+adjusting altitude and pitch angle only. It is implemented using an iterative,
+one-axis-at-a-time scheme.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGTRIM_H
+#define FGTRIM_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFDMExec.h"
+#include "FGJSBBase.h"
+#include "FGTrimAxis.h"
+
+#include <vector>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_TRIM "$Id$"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  #define snprintf _snprintf
+#endif
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+typedef enum { tLongitudinal=0, tFull, tGround, tPullup,
+               tCustom, tTurn, tNone } TrimMode;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** FGTrim -- the trimming routine for JSBSim.
+    FGTrim finds the aircraft attitude and control settings needed to maintain
+    the steady state described by the FGInitialCondition object .  It does this
+    iteratively by assigning a control to each state and adjusting that control
+    until the state is within a specified tolerance of zero. States include the
+    recti-linear accelerations udot, vdot, and wdot, the angular accelerations
+    qdot, pdot, and rdot, and the difference between heading and ground track.
+    Controls include the usual flight deck controls available to the pilot plus
+    angle of attack (alpha), sideslip angle(beta), flight path angle (gamma),
+    pitch attitude(theta), roll attitude(phi), and altitude above ground.  The
+    last three are used for on-ground trimming. The state-control pairs used in
+    a given trim are completely user configurable and several pre-defined modes
+    are provided as well. They are:
+    - tLongitudinal: Trim wdot with alpha, udot with thrust, qdot with elevator
+    - tFull: tLongitudinal + vdot with phi, pdot with aileron, rdot with rudder
+             and heading minus ground track (hmgt) with beta
+    - tPullup: tLongitudinal but adjust alpha to achieve load factor input
+               with SetTargetNlf()
+    - tGround: wdot with altitude, qdot with theta, and pdot with phi
+
+    The remaining modes include <b>tCustom</b>, which is completely user defined and
+    <b>tNone</b>.
+
+    Note that trims can (and do) fail for reasons that are completely outside
+    the control of the trimming routine itself. The most common problem is the
+    initial conditions: is the model capable of steady state flight
+    at those conditions?  Check the speed, altitude, configuration (flaps,
+    gear, etc.), weight, cg, and anything else that may be relevant.
+
+    Example usage:<pre>
+    FGFDMExec* FDMExec = new FGFDMExec();
+
+    FGInitialCondition* fgic = new FGInitialCondition(FDMExec);
+    FGTrim fgt(FDMExec, fgic, tFull);
+    fgic->SetVcaibratedKtsIC(100);
+    fgic->SetAltitudeFtIC(1000);
+    fgic->SetClimbRate(500);
+    if( !fgt.DoTrim() ) {
+      cout << "Trim Failed" << endl;
+    }
+    fgt.Report(); </pre>
+    @author Tony Peden
+    @version "$Id$"
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGTrim : public FGJSBBase
+{
+private:
+
+  vector<FGTrimAxis*> TrimAxes;
+  unsigned int current_axis;
+  int N, Nsub;
+  TrimMode mode;
+  int DebugLevel, Debug;
+  double Tolerance, A_Tolerance;
+  double wdot,udot,qdot;
+  double dth;
+  double *sub_iterations;
+  double *successful;
+  bool *solution;
+  int max_sub_iterations;
+  int max_iterations;
+  int total_its;
+  bool trimudot;
+  bool gamma_fallback;
+  bool trim_failed;
+  unsigned int axis_count;
+  int solutionDomain;
+  double xlo,xhi,alo,ahi;
+  double targetNlf;
+  int debug_axis;
+
+  double psidot,thetadot;
+
+  FGFDMExec* fdmex;
+  FGInitialCondition* fgic;
+
+  bool solve(void);
+
+  /** @return false if there is no change in the current axis accel
+      between accel(control_min) and accel(control_max). If there is a
+      change, sets solutionDomain to:
+      0 for no sign change,
+     -1 if sign change between accel(control_min) and accel(0)
+      1 if sign between accel(0) and accel(control_max)
+  */
+  bool findInterval(void);
+
+  bool checkLimits(void);
+
+  void setupPullup(void);
+  void setupTurn(void);
+
+  void updateRates(void);
+
+  void setDebug(void);
+
+public:
+  /** Initializes the trimming class
+      @param FDMExec pointer to a JSBSim executive object.
+      @param tm trim mode
+  */
+  FGTrim(FGFDMExec *FDMExec, TrimMode tm=tGround );
+
+  ~FGTrim(void);
+
+  /** Execute the trim
+  */
+  bool DoTrim(void);
+
+  /** Print the results of the trim. For each axis trimmed, this
+      includes the final state value, control value, and tolerance
+      used.
+      @return true if trim succeeds
+  */
+  void Report(void);
+
+  /** Iteration statistics
+  */
+  void TrimStats();
+
+  /** Clear all state-control pairs and set a predefined trim mode
+      @param tm the set of axes to trim. Can be:
+             tLongitudinal, tFull, tGround, tCustom, or tNone
+  */
+  void SetMode(TrimMode tm);
+
+  /** Clear all state-control pairs from the current configuration.
+      The trimming routine must have at least one state-control pair
+      configured to be useful
+  */
+  void ClearStates(void);
+
+  /** Add a state-control pair to the current configuration. See the enums
+      State and Control in FGTrimAxis.h for the available options.
+      Will fail if the given state is already configured.
+      @param state the accel or other condition to zero
+      @param control the control used to zero the state
+      @return true if add is successful
+  */
+  bool AddState( State state, Control control );
+
+  /** Remove a specific state-control pair from the current configuration
+      @param state the state to remove
+      @return true if removal is successful
+  */
+  bool RemoveState( State state );
+
+  /** Change the control used to zero a state previously configured
+      @param state the accel or other condition to zero
+      @param new_control the control used to zero the state
+  */
+  bool EditState( State state, Control new_control );
+
+  /** automatically switch to trimming longitudinal acceleration with
+      flight path angle (gamma) once it becomes apparent that there
+      is not enough/too much thrust.
+      @param bb true to enable fallback
+  */
+  inline void SetGammaFallback(bool bb) { gamma_fallback=bb; }
+
+  /** query the fallback state
+      @return true if fallback is enabled.
+  */
+  inline bool GetGammaFallback(void) { return gamma_fallback; }
+
+  /** Set the iteration limit. DoTrim() will return false if limit
+      iterations are reached before trim is achieved.  The default
+      is 60.  This does not ordinarily need to be changed.
+      @param ii integer iteration limit
+  */
+  inline void SetMaxCycles(int ii) { max_iterations = ii; }
+
+  /** Set the per-axis iteration limit.  Attempt to zero each state
+      by iterating limit times before moving on to the next. The
+      default limit is 100 and also does not ordinarily need to
+      be changed.
+      @param ii integer iteration limit
+  */
+  inline void SetMaxCyclesPerAxis(int ii) { max_sub_iterations = ii; }
+
+  /** Set the tolerance for declaring a state trimmed. Angular accels are
+      held to a tolerance of 1/10th of the given.  The default is
+      0.001 for the recti-linear accelerations and 0.0001 for the angular.
+  */
+  inline void SetTolerance(double tt) {
+    Tolerance = tt;
+    A_Tolerance = tt / 10;
+  }
+
+  /**
+    Debug level 1 shows results of each top-level iteration
+    Debug level 2 shows level 1 & results of each per-axis iteration
+  */
+  inline void SetDebug(int level) { DebugLevel = level; }
+  inline void ClearDebug(void) { DebugLevel = 0; }
+
+  /**
+    Output debug data for one of the axes
+    The State enum is defined in FGTrimAxis.h
+  */
+  inline void DebugState(State state) { debug_axis=state; }
+
+  inline void SetTargetNlf(double nlf) { targetNlf=nlf; }
+  inline double GetTargetNlf(void) { return targetNlf; }
+
+};
+}
+
+#endif
diff --git a/src/FDM/JSBSim/initialization/FGTrimAxis.cpp b/src/FDM/JSBSim/initialization/FGTrimAxis.cpp
new file mode 100644 (file)
index 0000000..3cea972
--- /dev/null
@@ -0,0 +1,500 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef _MSC_VER
+#  pragma warning (disable : 4786)
+#endif
+
+#include <string>
+#include <stdlib.h>
+
+#include <FGFDMExec.h>
+#include <models/FGAtmosphere.h>
+#include "FGInitialCondition.h"
+#include "FGTrimAxis.h"
+#include <models/FGAircraft.h>
+#include <models/FGPropulsion.h>
+#include <models/FGAerodynamics.h>
+
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_TRIMAXIS;
+
+/*****************************************************************************/
+
+FGTrimAxis::FGTrimAxis(FGFDMExec* fdex, FGInitialCondition* ic, State st,
+                       Control ctrl) {
+
+  fdmex=fdex;
+  fgic=ic;
+  state=st;
+  control=ctrl;
+  max_iterations=10;
+  control_value=0;
+  its_to_stable_value=0;
+  total_iterations=0;
+  total_stability_iterations=0;
+  state_convert=1.0;
+  control_convert=1.0;
+  state_value=0;
+  state_target=0;
+  switch(state) {
+    case tUdot: tolerance = DEFAULT_TOLERANCE; break;
+    case tVdot: tolerance = DEFAULT_TOLERANCE; break;
+    case tWdot: tolerance = DEFAULT_TOLERANCE; break;
+    case tQdot: tolerance = DEFAULT_TOLERANCE / 10; break;
+    case tPdot: tolerance = DEFAULT_TOLERANCE / 10; break;
+    case tRdot: tolerance = DEFAULT_TOLERANCE / 10; break;
+    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:
+    control_min=0;
+    control_max=1;
+    control_value=0.5;
+    break;
+  case tBeta:
+    control_min=-30*degtorad;
+    control_max=30*degtorad;
+    control_convert=radtodeg;
+    break;
+  case tAlpha:
+    control_min=fdmex->GetAerodynamics()->GetAlphaCLMin();
+    control_max=fdmex->GetAerodynamics()->GetAlphaCLMax();
+    if(control_max <= control_min) {
+      control_max=20*degtorad;
+      control_min=-5*degtorad;
+    }
+    control_value= (control_min+control_max)/2;
+    control_convert=radtodeg;
+    solver_eps=tolerance/100;
+    break;
+  case tPitchTrim:
+  case tElevator:
+  case tRollTrim:
+  case tAileron:
+  case tYawTrim:
+  case tRudder:
+    control_min=-1;
+    control_max=1;
+    state_convert=radtodeg;
+    solver_eps=tolerance/100;
+    break;
+  case tAltAGL:
+    control_min=0;
+    control_max=30;
+    control_value=fdmex->GetPropagate()->GetDistanceAGL();
+    solver_eps=tolerance/100;
+    break;
+  case tTheta:
+    control_min=fdmex->GetPropagate()->GetEuler(eTht) - 5*degtorad;
+    control_max=fdmex->GetPropagate()->GetEuler(eTht) + 5*degtorad;
+    state_convert=radtodeg;
+    break;
+  case tPhi:
+    control_min=fdmex->GetPropagate()->GetEuler(ePhi) - 30*degtorad;
+    control_max=fdmex->GetPropagate()->GetEuler(ePhi) + 30*degtorad;
+    state_convert=radtodeg;
+    control_convert=radtodeg;
+    break;
+  case tGamma:
+    solver_eps=tolerance/100;
+    control_min=-80*degtorad;
+    control_max=80*degtorad;
+    control_convert=radtodeg;
+    break;
+  case tHeading:
+    control_min=fdmex->GetPropagate()->GetEuler(ePsi) - 30*degtorad;
+    control_max=fdmex->GetPropagate()->GetEuler(ePsi) + 30*degtorad;
+    state_convert=radtodeg;
+    break;
+  }
+
+
+  Debug(0);
+}
+
+/*****************************************************************************/
+
+FGTrimAxis::~FGTrimAxis(void)
+{
+  Debug(1);
+}
+
+/*****************************************************************************/
+
+void FGTrimAxis::getState(void) {
+  switch(state) {
+  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;
+  }
+}
+
+/*****************************************************************************/
+
+//States are not settable
+
+void FGTrimAxis::getControl(void) {
+  switch(control) {
+  case tThrottle:  control_value=fdmex->GetFCS()->GetThrottleCmd(0); 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->GetPropagate()->GetDistanceAGL();break;
+  case tTheta:     control_value=fdmex->GetPropagate()->GetEuler(eTht); break;
+  case tPhi:       control_value=fdmex->GetPropagate()->GetEuler(ePhi); break;
+  case tGamma:     control_value=fdmex->GetAuxiliary()->GetGamma();break;
+  case tHeading:   control_value=fdmex->GetPropagate()->GetEuler(ePsi); break;
+  }
+}
+
+/*****************************************************************************/
+
+double FGTrimAxis::computeHmgt(void) {
+  double diff;
+
+  diff   = fdmex->GetPropagate()->GetEuler(ePsi) -
+             fdmex->GetAuxiliary()->GetGroundTrack();
+
+  if( diff < -M_PI ) {
+     return (diff + 2*M_PI);
+  } else if( diff > M_PI ) {
+     return (diff - 2*M_PI);
+  } else {
+     return diff;
+  }
+
+}
+
+/*****************************************************************************/
+
+
+void FGTrimAxis::setControl(void) {
+  switch(control) {
+  case tThrottle:  setThrottlesPct(); break;
+  case tBeta:      fgic->SetBetaRadIC(control_value); break;
+  case tAlpha:     fgic->SetAlphaRadIC(control_value);  break;
+  case tPitchTrim: fdmex->GetFCS()->SetPitchTrimCmd(control_value); break;
+  case tElevator:  fdmex->GetFCS()->SetDeCmd(control_value); break;
+  case tRollTrim:
+  case tAileron:   fdmex->GetFCS()->SetDaCmd(control_value); break;
+  case tYawTrim:
+  case tRudder:    fdmex->GetFCS()->SetDrCmd(control_value); break;
+  case tAltAGL:    fgic->SetAltitudeAGLFtIC(control_value); break;
+  case tTheta:     fgic->SetPitchAngleRadIC(control_value); break;
+  case tPhi:       fgic->SetRollAngleRadIC(control_value); break;
+  case tGamma:     fgic->SetFlightPathAngleRadIC(control_value); break;
+  case tHeading:   fgic->SetTrueHeadingRadIC(control_value); break;
+  }
+}
+
+
+
+
+
+/*****************************************************************************/
+
+// 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
+// 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 )
+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
+  // that's in contact with the ground.
+  i=0; ref=-1; center=-1;
+  while( (ref < 0) && (i < fdmex->GetGroundReactions()->GetNumGearUnits()) ) {
+    if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetWOW()) {
+      if(fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01)
+        ref=i;
+      else
+        center=i;
+    }
+    i++;
+  }
+  if((ref < 0) && (center >= 0)) {
+    ref=center;
+  }
+  cout << "SetThetaOnGround ref gear: " << ref << endl;
+  if(ref >= 0) {
+    double sp = fdmex->GetPropagate()->GetSinEuler(ePhi);
+    double cp = fdmex->GetPropagate()->GetCosEuler(ePhi);
+    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;
+}
+
+/*****************************************************************************/
+
+bool FGTrimAxis::initTheta(void) {
+  int i,N;
+  int iForward = 0;
+  int iAft = 1;
+  double zAft,zForward,zDiff,theta;
+  double xAft,xForward,xDiff;
+  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++ ) {
+    if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) > 0 ) {
+        iForward=i;
+        break;
+    }
+  }
+  //now find the first wheel unit aft of the cg
+  for( i=0; i<N; i++ ) {
+    if(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(1) < 0 ) {
+        iAft=i;
+        break;
+    }
+  }
+
+  // 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 << i << endl;
+  if (debug_lvl > 0) {
+      cout << "    Initial Theta: " << fdmex->GetPropagate()->GetEuler(eTht)*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)
+    return true;
+  else
+    return false;
+}
+
+/*****************************************************************************/
+
+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()) &&
+      (fabs(fdmex->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation(2)) > 0.01))
+        ref=i;
+    i++;
+  }
+  if (ref >= 0) {
+    double st = fdmex->GetPropagate()->GetSinEuler(eTht);
+    double ct = fdmex->GetPropagate()->GetCosEuler(eTht);
+    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);
+
+}
+
+/*****************************************************************************/
+
+void FGTrimAxis::Run(void) {
+
+  double last_state_value;
+  int i;
+  setControl();
+  //cout << "FGTrimAxis::Run: " << control_value << endl;
+  i=0;
+  bool stable=false;
+  while(!stable) {
+    i++;
+    last_state_value=state_value;
+    fdmex->RunIC();
+    getState();
+    if(i > 1) {
+      if((fabs(last_state_value - state_value) < tolerance) || (i >= 100) )
+        stable=true;
+    }
+  }
+
+  its_to_stable_value=i;
+  total_stability_iterations+=its_to_stable_value;
+  total_iterations++;
+}
+
+/*****************************************************************************/
+
+void FGTrimAxis::setThrottlesPct(void) {
+  double tMin,tMax;
+  for(unsigned i=0;i<fdmex->GetPropulsion()->GetNumEngines();i++) {
+      tMin=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMin();
+      tMax=fdmex->GetPropulsion()->GetEngine(i)->GetThrottleMax();
+      //cout << "setThrottlespct: " << i << ", " << control_min << ", " << control_max << ", " << control_value;
+      fdmex->GetFCS()->SetThrottleCmd(i,tMin+control_value*(tMax-tMin));
+      //cout << "setThrottlespct: " << fdmex->GetFCS()->GetThrottleCmd(i) << endl;
+      fdmex->RunIC(); //apply throttle change
+      fdmex->GetPropulsion()->GetSteadyState();
+  }
+}
+
+/*****************************************************************************/
+
+void FGTrimAxis::AxisReport(void) {
+
+  char out[80];
+
+  sprintf(out,"  %20s: %6.2f %5s: %9.2e Tolerance: %3.0e",
+           GetControlName().c_str(), GetControl()*control_convert,
+           GetStateName().c_str(), GetState()+state_target, GetTolerance());
+  cout << out;
+
+  if( fabs(GetState()+state_target) < fabs(GetTolerance()) )
+     cout << "  Passed" << endl;
+  else
+     cout << "  Failed" << endl;
+}
+
+/*****************************************************************************/
+
+double FGTrimAxis::GetAvgStability( void ) {
+  if(total_iterations > 0) {
+    return double(total_stability_iterations)/double(total_iterations);
+  }
+  return 0;
+}
+
+/*****************************************************************************/
+//    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 FGTrimAxis::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: FGTrimAxis" << endl;
+    if (from == 1) cout << "Destroyed:    FGTrimAxis" << 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/initialization/FGTrimAxis.h b/src/FDM/JSBSim/initialization/FGTrimAxis.h
new file mode 100644 (file)
index 0000000..e0754a0
--- /dev/null
@@ -0,0 +1,186 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGTrimAxis.h
+ 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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGTRIMAXIS_H
+#define FGTRIMAXIS_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <string>
+
+#include "FGFDMExec.h"
+#include "FGJSBBase.h"
+#include "FGInitialCondition.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_TRIMAXIS "$Id$"
+
+#define DEFAULT_TOLERANCE 0.001
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+const string StateNames[10]=   { "all","udot","vdot","wdot","qdot","pdot","rdot",
+                                "hmgt","nlf" 
+                              };
+const string ControlNames[14]= { "Throttle","Sideslip","Angle of Attack",
+                                 "Elevator","Ailerons","Rudder",
+                                 "Altitude AGL", "Pitch Angle",
+                                 "Roll Angle", "Flight Path Angle", 
+                                 "Pitch Trim", "Roll Trim", "Yaw Trim",
+                                 "Heading"
+                               };
+
+class FGInitialCondition;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models an aircraft axis for purposes of trimming.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+enum State { tAll,tUdot,tVdot,tWdot,tQdot,tPdot,tRdot,tHmgt,tNlf };
+enum Control { tThrottle, tBeta, tAlpha, tElevator, tAileron, tRudder, tAltAGL,
+               tTheta, tPhi, tGamma, tPitchTrim, tRollTrim, tYawTrim, tHeading };
+
+class FGTrimAxis : public FGJSBBase
+{
+public:
+  FGTrimAxis(FGFDMExec* fdmex, 
+             FGInitialCondition *ic, 
+             State st,
+             Control ctrl );
+  ~FGTrimAxis();
+
+  void Run(void);
+  double GetState(void) { getState(); return state_value; }
+  //Accels are not settable
+  inline void SetControl(double value ) { control_value=value; }
+  inline double GetControl(void) { return control_value; }
+
+  inline State GetStateType(void) { return state; }
+  inline Control GetControlType(void) { return control; }
+
+  inline string GetStateName(void) { return StateNames[state]; }
+  inline string GetControlName(void) { return ControlNames[control]; }
+
+  inline double GetControlMin(void) { return control_min; }
+  inline double GetControlMax(void) { return control_max; }
+
+  inline void SetControlToMin(void) { control_value=control_min; }
+  inline void SetControlToMax(void) { control_value=control_max; }
+  
+  inline void SetControlLimits(double min, double max) { 
+      control_min=min;
+      control_max=max;
+  }    
+
+  inline void  SetTolerance(double ff) { tolerance=ff;}
+  inline double GetTolerance(void) { return tolerance; }
+
+  inline double GetSolverEps(void) { return solver_eps; }
+  inline void SetSolverEps(double ff) { solver_eps=ff; }
+
+  inline int  GetIterationLimit(void) { return max_iterations; }
+  inline void SetIterationLimit(int ii) { max_iterations=ii; }
+
+  inline int GetStability(void) { return its_to_stable_value; }
+  inline int GetRunCount(void) { return total_stability_iterations; }
+  double GetAvgStability( void );
+  
+  void SetThetaOnGround(double ff);
+  void SetPhiOnGround(double ff);
+  
+  inline void SetStateTarget(double target) { state_target=target; }
+  inline double GetStateTarget(void) { return state_target; }
+  
+  bool initTheta(void);
+  
+  void AxisReport(void);
+  
+  bool InTolerance(void) { getState(); return (fabs(state_value) <= tolerance); }
+
+private:
+  FGFDMExec *fdmex;
+  FGInitialCondition *fgic;
+
+  State   state;
+  Control control;
+  
+  double state_target;
+  
+  double state_value;
+  double control_value;
+
+  double control_min;
+  double control_max;
+
+  double tolerance;
+
+  double solver_eps;
+
+  double state_convert;
+  double control_convert;
+
+  int max_iterations;
+
+  int its_to_stable_value;
+  int total_stability_iterations;
+  int total_iterations;
+
+  void setThrottlesPct(void);
+
+  void getState(void);
+  void getControl(void);
+  void setControl(void);
+  
+  double computeHmgt(void);
+  
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/initialization/Makefile.am b/src/FDM/JSBSim/initialization/Makefile.am
new file mode 100644 (file)
index 0000000..b88485a
--- /dev/null
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = libInit.a
+
+libInit_a_SOURCES = FGInitialCondition.cpp FGTrim.cpp FGTrimAxis.cpp
+
+noinst_HEADERS = FGInitialCondition.h FGTrim.h FGTrimAxis.h
+
+INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
diff --git a/src/FDM/JSBSim/input_output/FGGroundCallback.cpp b/src/FDM/JSBSim/input_output/FGGroundCallback.cpp
new file mode 100644 (file)
index 0000000..8b9a567
--- /dev/null
@@ -0,0 +1,74 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGGroundCallback.cpp
+ Author:       Mathias Froehlich
+ Date started: 05/21/04
+
+ ------ Copyright (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
+-------------------------------------------------------------------------------
+05/21/00   MF   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <math/FGColumnVector3.h>
+#include <math/FGLocation.h>
+#include "FGGroundCallback.h"
+
+namespace JSBSim {
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGGroundCallback::FGGroundCallback()
+{
+  mReferenceRadius = 20925650.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGGroundCallback::~FGGroundCallback()
+{
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGGroundCallback::GetAltitude(const FGLocation& loc) const
+{
+  return loc.GetRadius() - mReferenceRadius;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGGroundCallback::GetAGLevel(double t, const FGLocation& loc,
+                                    FGLocation& contact, FGColumnVector3& normal,
+                                    FGColumnVector3& vel) const
+{
+  vel = FGColumnVector3(0.0, 0.0, 0.0);
+  normal = (-1/FGColumnVector3(loc).Magnitude())*FGColumnVector3(loc);
+  double radius = loc.GetRadius();
+  double agl = GetAltitude(loc);
+  contact = ((radius-agl)/radius)*FGColumnVector3(loc);
+  return agl;
+}
+
+}
diff --git a/src/FDM/JSBSim/input_output/FGGroundCallback.h b/src/FDM/JSBSim/input_output/FGGroundCallback.h
new file mode 100644 (file)
index 0000000..8abffcf
--- /dev/null
@@ -0,0 +1,87 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGGroundCallback.h
+ Author:       Mathias Froehlich
+ Date started: 05/21/04
+
+ ------ Copyright (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
+-------------------------------------------------------------------------------
+05/21/00   MF   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGGROUNDCALLBACK_H
+#define FGGROUNDCALLBACK_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <math/FGColumnVector3.h>
+#include <math/FGLocation.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_GROUNDCALLBACK "$Id$"
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** This class provides callback slots to get ground specific data like
+    ground elevation and such.
+    There is a default implementation, which returns values for a
+    ball formed earth.
+
+    @author Mathias Froehlich
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGGroundCallback : public FGJSBBase
+{
+public:
+  FGGroundCallback();
+  virtual ~FGGroundCallback();
+
+  /** Compute the altitude above sealevel. */
+  virtual double GetAltitude(const FGLocation& l) const;
+  /** Compute the altitude above ground. Defaults to sealevel altitude. */
+  virtual double GetAGLevel(double t, const FGLocation& l, FGLocation& cont,
+                            FGColumnVector3& n, FGColumnVector3& v) const;
+private:
+  /// Reference radius.
+  double mReferenceRadius;
+};
+
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp
new file mode 100755 (executable)
index 0000000..63bc589
--- /dev/null
@@ -0,0 +1,321 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGPropertyManager.cpp
+ Author:       Tony Peden
+               Based on work originally by David Megginson
+ Date:         2/2002
+
+ ------------- Copyright (C) 2002 -------------
+
+ 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.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGPropertyManager.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+using namespace std;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+*/
+
+namespace JSBSim {
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
+
+  /* do this two pass to avoid problems with characters getting skipped
+     because the index changed */
+  unsigned i;
+  for(i=0;i<name.length();i++) {
+    if( lowercase && isupper(name[i]) )
+      name[i]=tolower(name[i]);
+    else if( isspace(name[i]) )
+      name[i]='-';
+  }
+  /*
+  for(i=0;i<name.length();i++) {
+    if( name[i] == '/' )
+      name.erase(i,1);
+  }
+  */
+  return name;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPropertyManager*
+FGPropertyManager::GetNode (const string &path, bool create)
+{
+  SGPropertyNode* node=this->getNode(path.c_str(), create);
+  if (node == 0 && !suppress_warning)
+    cout << "FGPropertyManager::GetNode() No node found for "
+         << path << endl;
+  return (FGPropertyManager*)node;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPropertyManager*
+FGPropertyManager::GetNode (const string &relpath, int index, bool create)
+{
+    return (FGPropertyManager*)getNode(relpath.c_str(),index,create);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+bool FGPropertyManager::HasNode (const string &path)
+{
+  // Checking if a node exists shouldn't write a warning if it doesn't exist
+  suppress_warning = true;
+  bool has_node = (GetNode(path, false) != 0);
+  suppress_warning = false;
+  return has_node;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropertyManager::GetName( void ) {
+  return string( getName() );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropertyManager::GetFullyQualifiedName(void) {
+    vector<string> stack;
+    stack.push_back( getDisplayName(true) );
+    SGPropertyNode* tmpn=getParent();
+    bool atroot=false;
+    while( !atroot ) {
+     stack.push_back( tmpn->getDisplayName(true) );
+     if( !tmpn->getParent() )
+      atroot=true;
+     else
+      tmpn=tmpn->getParent();
+    }
+
+    string fqname="";
+    for(unsigned i=stack.size()-1;i>0;i--) {
+      fqname+= stack[i];
+      fqname+= "/";
+    }
+    fqname+= stack[0];
+    return fqname;
+
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropertyManager::GetBool (const string &name, bool defaultValue)
+{
+  return getBoolValue(name.c_str(), defaultValue);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+int FGPropertyManager::GetInt (const string &name, int defaultValue )
+{
+  return getIntValue(name.c_str(), defaultValue);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+int FGPropertyManager::GetLong (const string &name, long defaultValue )
+{
+  return getLongValue(name.c_str(), defaultValue);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+float FGPropertyManager::GetFloat (const string &name, float defaultValue )
+{
+  return getFloatValue(name.c_str(), defaultValue);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGPropertyManager::GetDouble (const string &name, double defaultValue )
+{
+  return getDoubleValue(name.c_str(), defaultValue);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropertyManager::GetString (const string &name, string defaultValue )
+{
+  return string(getStringValue(name.c_str(), defaultValue.c_str()));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropertyManager::SetBool (const string &name, bool val)
+{
+  return setBoolValue(name.c_str(), val);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropertyManager::SetInt (const string &name, int val)
+{
+  return setIntValue(name.c_str(), val);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropertyManager::SetLong (const string &name, long val)
+{
+  return setLongValue(name.c_str(), val);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropertyManager::SetFloat (const string &name, float val)
+{
+  return setFloatValue(name.c_str(), val);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropertyManager::SetDouble (const string &name, double val)
+{
+  return setDoubleValue(name.c_str(), val);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropertyManager::SetString (const string &name, const string &val)
+{
+  return setStringValue(name.c_str(), val.c_str());
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::SetArchivable (const string &name, bool state )
+{
+  SGPropertyNode * node = getNode(name.c_str());
+  if (node == 0)
+    cout <<
+           "Attempt to set archive flag for non-existant property "
+           << name << endl;
+  else
+    node->setAttribute(SGPropertyNode::ARCHIVE, state);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::SetReadable (const string &name, bool state )
+{
+  SGPropertyNode * node = getNode(name.c_str());
+  if (node == 0)
+    cout <<
+           "Attempt to set read flag for non-existant property "
+           << name << endl;
+  else
+    node->setAttribute(SGPropertyNode::READ, state);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::SetWritable (const string &name, bool state )
+{
+  SGPropertyNode * node = getNode(name.c_str());
+  if (node == 0)
+    cout <<
+           "Attempt to set write flag for non-existant property "
+           << name << endl;
+  else
+    node->setAttribute(SGPropertyNode::WRITE, state);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::Untie (const string &name)
+{
+  if (!untie(name.c_str()))
+    cout << "Failed to untie property " << name << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
+{
+  if (!tie(name.c_str(), SGRawValuePointer<bool>(pointer), useDefault))
+    cout << "Failed to tie property " << name << " to a pointer" << endl;
+  else if (debug_lvl & 0x20)
+    cout << name << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::Tie (const string &name, int *pointer,
+                                          bool useDefault )
+{
+  if (!tie(name.c_str(), SGRawValuePointer<int>(pointer), useDefault))
+    cout << "Failed to tie property " << name << " to a pointer" << endl;
+  else if (debug_lvl & 0x20)
+    cout << name << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::Tie (const string &name, long *pointer,
+                                          bool useDefault )
+{
+  if (!tie(name.c_str(), SGRawValuePointer<long>(pointer), useDefault))
+    cout << "Failed to tie property " << name << " to a pointer" << endl;
+  else if (debug_lvl & 0x20)
+    cout << name << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::Tie (const string &name, float *pointer,
+                                          bool useDefault )
+{
+  if (!tie(name.c_str(), SGRawValuePointer<float>(pointer), useDefault))
+    cout << "Failed to tie property " << name << " to a pointer" << endl;
+  else if (debug_lvl & 0x20)
+    cout << name << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault)
+{
+  if (!tie(name.c_str(), SGRawValuePointer<double>(pointer), useDefault))
+    cout << "Failed to tie property " << name << " to a pointer" << endl;
+  else if (debug_lvl & 0x20)
+    cout << name << endl;
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.h b/src/FDM/JSBSim/input_output/FGPropertyManager.h
new file mode 100644 (file)
index 0000000..284c747
--- /dev/null
@@ -0,0 +1,605 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGPropertyManager.h
+ Author:       Tony Peden
+               Based on work originally by David Megginson
+ Date:         2/2002
+
+ ------------- Copyright (C) 2002 -------------
+
+ 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.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGPROPERTYMANAGER_H
+#define FGPROPERTYMANAGER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <string>
+#ifdef FGFS
+#  include <simgear/props/props.hxx>
+#else
+#  include "simgear/props/props.hxx"
+#endif
+
+#include "FGJSBBase.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_PROPERTYMANAGER "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+using namespace std;
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Class wrapper for property handling.
+    @author David Megginson, Tony Peden
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGPropertyManager : public SGPropertyNode, public FGJSBBase
+{
+  private:
+    bool suppress_warning;
+  public:
+    /// Constructor
+    FGPropertyManager(void) {suppress_warning = false;}
+    /// Destructor
+    ~FGPropertyManager(void) {}
+
+    /** Property-ify a name
+     *  replaces spaces with '-' and, optionally, makes name all lower case
+     *  @param name string to change
+     *  @param lowercase true to change all upper case chars to lower
+     *  NOTE: this function changes its argument and thus relies
+     *  on pass by value
+     */
+    string mkPropertyName(string name, bool lowercase);
+
+    /**
+     * Get a property node.
+     *
+     * @param path The path of the node, relative to root.
+     * @param create true to create the node if it doesn't exist.
+     * @return The node, or 0 if none exists and none was created.
+     */
+    FGPropertyManager*
+    GetNode (const string &path, bool create = false);
+
+    FGPropertyManager*
+    GetNode (const string &relpath, int index, bool create = false);
+
+    /**
+     * Test whether a given node exists.
+     *
+     * @param path The path of the node, relative to root.
+     * @return true if the node exists, false otherwise.
+     */
+    bool HasNode (const string &path);
+
+    /**
+     * Get the name of a node
+     */
+    string GetName( void );
+
+    /**
+     * Get the fully qualified name of a node
+     * This function is very slow, so is probably useful for debugging only.
+     */
+    string GetFullyQualifiedName(void);
+
+    /**
+     * Get a bool value for a property.
+     *
+     * This method is convenient but inefficient.  It should be used
+     * infrequently (i.e. for initializing, loading, saving, etc.),
+     * not in the main loop.  If you need to get a value frequently,
+     * it is better to look up the node itself using GetNode and then
+     * use the node's getBoolValue() method, to avoid the lookup overhead.
+     *
+     * @param name The property name.
+     * @param defaultValue The default value to return if the property
+     *        does not exist.
+     * @return The property's value as a bool, or the default value provided.
+     */
+    bool GetBool (const string &name, bool defaultValue = false);
+
+
+    /**
+     * Get an int value for a property.
+     *
+     * This method is convenient but inefficient.  It should be used
+     * infrequently (i.e. for initializing, loading, saving, etc.),
+     * not in the main loop.  If you need to get a value frequently,
+     * it is better to look up the node itself using GetNode and then
+     * use the node's getIntValue() method, to avoid the lookup overhead.
+     *
+     * @param name The property name.
+     * @param defaultValue The default value to return if the property
+     *        does not exist.
+     * @return The property's value as an int, or the default value provided.
+     */
+    int GetInt (const string &name, int defaultValue = 0);
+
+
+    /**
+     * Get a long value for a property.
+     *
+     * This method is convenient but inefficient.  It should be used
+     * infrequently (i.e. for initializing, loading, saving, etc.),
+     * not in the main loop.  If you need to get a value frequently,
+     * it is better to look up the node itself using GetNode and then
+     * use the node's getLongValue() method, to avoid the lookup overhead.
+     *
+     * @param name The property name.
+     * @param defaultValue The default value to return if the property
+     *        does not exist.
+     * @return The property's value as a long, or the default value provided.
+     */
+    int GetLong (const string &name, long defaultValue = 0L);
+
+
+    /**
+     * Get a float value for a property.
+     *
+     * This method is convenient but inefficient.  It should be used
+     * infrequently (i.e. for initializing, loading, saving, etc.),
+     * not in the main loop.  If you need to get a value frequently,
+     * it is better to look up the node itself using GetNode and then
+     * use the node's getFloatValue() method, to avoid the lookup overhead.
+     *
+     * @param name The property name.
+     * @param defaultValue The default value to return if the property
+     *        does not exist.
+     * @return The property's value as a float, or the default value provided.
+     */
+    float GetFloat (const string &name, float defaultValue = 0.0);
+
+
+    /**
+     * Get a double value for a property.
+     *
+     * This method is convenient but inefficient.  It should be used
+     * infrequently (i.e. for initializing, loading, saving, etc.),
+     * not in the main loop.  If you need to get a value frequently,
+     * it is better to look up the node itself using GetNode and then
+     * use the node's getDoubleValue() method, to avoid the lookup overhead.
+     *
+     * @param name The property name.
+     * @param defaultValue The default value to return if the property
+     *        does not exist.
+     * @return The property's value as a double, or the default value provided.
+     */
+    double GetDouble (const string &name, double defaultValue = 0.0);
+
+
+    /**
+     * Get a string value for a property.
+     *
+     * This method is convenient but inefficient.  It should be used
+     * infrequently (i.e. for initializing, loading, saving, etc.),
+     * not in the main loop.  If you need to get a value frequently,
+     * it is better to look up the node itself using GetNode and then
+     * use the node's getStringValue() method, to avoid the lookup overhead.
+     *
+     * @param name The property name.
+     * @param defaultValue The default value to return if the property
+     *        does not exist.
+     * @return The property's value as a string, or the default value provided.
+     */
+    string GetString (const string &name, string defaultValue = "");
+
+
+    /**
+     * Set a bool value for a property.
+     *
+     * Assign a bool value to a property.  If the property does not
+     * yet exist, it will be created and its type will be set to
+     * BOOL; if it has a type of UNKNOWN, the type will also be set to
+     * BOOL; otherwise, the bool value will be converted to the property's
+     * type.
+     *
+     * @param name The property name.
+     * @param val The new value for the property.
+     * @return true if the assignment succeeded, false otherwise.
+     */
+    bool SetBool (const string &name, bool val);
+
+
+    /**
+     * Set an int value for a property.
+     *
+     * Assign an int value to a property.  If the property does not
+     * yet exist, it will be created and its type will be set to
+     * INT; if it has a type of UNKNOWN, the type will also be set to
+     * INT; otherwise, the bool value will be converted to the property's
+     * type.
+     *
+     * @param name The property name.
+     * @param val The new value for the property.
+     * @return true if the assignment succeeded, false otherwise.
+     */
+    bool SetInt (const string &name, int val);
+
+
+    /**
+     * Set a long value for a property.
+     *
+     * Assign a long value to a property.  If the property does not
+     * yet exist, it will be created and its type will be set to
+     * LONG; if it has a type of UNKNOWN, the type will also be set to
+     * LONG; otherwise, the bool value will be converted to the property's
+     * type.
+     *
+     * @param name The property name.
+     * @param val The new value for the property.
+     * @return true if the assignment succeeded, false otherwise.
+     */
+    bool SetLong (const string &name, long val);
+
+
+    /**
+     * Set a float value for a property.
+     *
+     * Assign a float value to a property.  If the property does not
+     * yet exist, it will be created and its type will be set to
+     * FLOAT; if it has a type of UNKNOWN, the type will also be set to
+     * FLOAT; otherwise, the bool value will be converted to the property's
+     * type.
+     *
+     * @param name The property name.
+     * @param val The new value for the property.
+     * @return true if the assignment succeeded, false otherwise.
+     */
+    bool SetFloat (const string &name, float val);
+
+
+    /**
+     * Set a double value for a property.
+     *
+     * Assign a double value to a property.  If the property does not
+     * yet exist, it will be created and its type will be set to
+     * DOUBLE; if it has a type of UNKNOWN, the type will also be set to
+     * DOUBLE; otherwise, the double value will be converted to the property's
+     * type.
+     *
+     * @param name The property name.
+     * @param val The new value for the property.
+     * @return true if the assignment succeeded, false otherwise.
+     */
+    bool SetDouble (const string &name, double val);
+
+
+    /**
+     * Set a string value for a property.
+     *
+     * Assign a string value to a property.  If the property does not
+     * yet exist, it will be created and its type will be set to
+     * STRING; if it has a type of UNKNOWN, the type will also be set to
+     * STRING; otherwise, the string value will be converted to the property's
+     * type.
+     *
+     * @param name The property name.
+     * @param val The new value for the property.
+     * @return true if the assignment succeeded, false otherwise.
+     */
+    bool SetString (const string &name, const string &val);
+
+
+    ////////////////////////////////////////////////////////////////////////
+    // Convenience functions for setting property attributes.
+    ////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set the state of the archive attribute for a property.
+     *
+     * If the archive attribute is true, the property will be written
+     * when a flight is saved; if it is false, the property will be
+     * skipped.
+     *
+     * A warning message will be printed if the property does not exist.
+     *
+     * @param name The property name.
+     * @param state The state of the archive attribute (defaults to true).
+     */
+    void SetArchivable (const string &name, bool state = true);
+
+
+    /**
+     * Set the state of the read attribute for a property.
+     *
+     * If the read attribute is true, the property value will be readable;
+     * if it is false, the property value will always be the default value
+     * for its type.
+     *
+     * A warning message will be printed if the property does not exist.
+     *
+     * @param name The property name.
+     * @param state The state of the read attribute (defaults to true).
+     */
+    void SetReadable (const string &name, bool state = true);
+
+
+    /**
+     * Set the state of the write attribute for a property.
+     *
+     * If the write attribute is true, the property value may be modified
+     * (depending on how it is tied); if the write attribute is false, the
+     * property value may not be modified.
+     *
+     * A warning message will be printed if the property does not exist.
+     *
+     * @param name The property name.
+     * @param state The state of the write attribute (defaults to true).
+     */
+    void SetWritable (const string &name, bool state = true);
+
+
+    ////////////////////////////////////////////////////////////////////////
+    // Convenience functions for tying properties, with logging.
+    ////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Untie a property from an external data source.
+     *
+     * Classes should use this function to release control of any
+     * properties they are managing.
+     */
+    void Untie (const string &name);
+
+
+        // Templates cause ambiguity here
+
+    /**
+     * Tie a property to an external bool variable.
+     *
+     * The property's value will automatically mirror the variable's
+     * value, and vice-versa, until the property is untied.
+     *
+     * @param name The property name to tie (full path).
+     * @param pointer A pointer to the variable.
+     * @param useDefault true if any existing property value should be
+     *        copied to the variable; false if the variable should not
+     *        be modified; defaults to true.
+     */
+    void
+    Tie (const string &name, bool *pointer, bool useDefault = true);
+
+
+    /**
+     * Tie a property to an external int variable.
+     *
+     * The property's value will automatically mirror the variable's
+     * value, and vice-versa, until the property is untied.
+     *
+     * @param name The property name to tie (full path).
+     * @param pointer A pointer to the variable.
+     * @param useDefault true if any existing property value should be
+     *        copied to the variable; false if the variable should not
+     *        be modified; defaults to true.
+     */
+    void
+    Tie (const string &name, int *pointer, bool useDefault = true);
+
+
+    /**
+     * Tie a property to an external long variable.
+     *
+     * The property's value will automatically mirror the variable's
+     * value, and vice-versa, until the property is untied.
+     *
+     * @param name The property name to tie (full path).
+     * @param pointer A pointer to the variable.
+     * @param useDefault true if any existing property value should be
+     *        copied to the variable; false if the variable should not
+     *        be modified; defaults to true.
+     */
+    void
+    Tie (const string &name, long *pointer, bool useDefault = true);
+
+
+    /**
+     * Tie a property to an external float variable.
+     *
+     * The property's value will automatically mirror the variable's
+     * value, and vice-versa, until the property is untied.
+     *
+     * @param name The property name to tie (full path).
+     * @param pointer A pointer to the variable.
+     * @param useDefault true if any existing property value should be
+     *        copied to the variable; false if the variable should not
+     *        be modified; defaults to true.
+     */
+    void
+    Tie (const string &name, float *pointer, bool useDefault = true);
+
+    /**
+     * Tie a property to an external double variable.
+     *
+     * The property's value will automatically mirror the variable's
+     * value, and vice-versa, until the property is untied.
+     *
+     * @param name The property name to tie (full path).
+     * @param pointer A pointer to the variable.
+     * @param useDefault true if any existing property value should be
+     *        copied to the variable; false if the variable should not
+     *        be modified; defaults to true.
+     */
+    void
+    Tie (const string &name, double *pointer, bool useDefault = true);
+
+//============================================================================
+//
+//  All of the following functions *must* be inlined, otherwise linker
+//  errors will result
+//
+//============================================================================
+
+    /* template <class V> void
+    Tie (const string &name, V (*getter)(), void (*setter)(V) = 0,
+           bool useDefault = true);
+
+    template <class V> void
+    Tie (const string &name, int index, V (*getter)(int),
+           void (*setter)(int, V) = 0, bool useDefault = true);
+
+    template <class T, class V> void
+    Tie (const string &name, T * obj, V (T::*getter)() const,
+           void (T::*setter)(V) = 0, bool useDefault = true);
+
+    template <class T, class V> void
+    Tie (const string &name, T * obj, int index,
+           V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
+           bool useDefault = true); */
+
+     /**
+     * Tie a property to a pair of simple functions.
+     *
+     * Every time the property value is queried, the getter (if any) will
+     * be invoked; every time the property value is modified, the setter
+     * (if any) will be invoked.  The getter can be 0 to make the property
+     * unreadable, and the setter can be 0 to make the property
+     * unmodifiable.
+     *
+     * @param name The property name to tie (full path).
+     * @param getter The getter function, or 0 if the value is unreadable.
+     * @param setter The setter function, or 0 if the value is unmodifiable.
+     * @param useDefault true if the setter should be invoked with any existing
+     *        property value should be; false if the old value should be
+     *        discarded; defaults to true.
+     */
+
+    template <class V> inline void
+    Tie (const string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
+    {
+      if (!tie(name.c_str(), SGRawValueFunctions<V>(getter, setter), useDefault))
+        cout << "Failed to tie property " << name << " to functions" << endl;
+      else if (debug_lvl & 0x20)
+        cout << name << endl;
+    }
+
+
+    /**
+     * Tie a property to a pair of indexed functions.
+     *
+     * Every time the property value is queried, the getter (if any) will
+     * be invoked with the index provided; every time the property value
+     * is modified, the setter (if any) will be invoked with the index
+     * provided.  The getter can be 0 to make the property unreadable, and
+     * the setter can be 0 to make the property unmodifiable.
+     *
+     * @param name The property name to tie (full path).
+     * @param index The integer argument to pass to the getter and
+     *        setter functions.
+     * @param getter The getter function, or 0 if the value is unreadable.
+     * @param setter The setter function, or 0 if the value is unmodifiable.
+     * @param useDefault true if the setter should be invoked with any existing
+     *        property value should there be one; false if the old value should be
+     *        discarded; defaults to true.
+     */
+    template <class V> inline void Tie (const string &name, int index, V (*getter)(int),
+                                void (*setter)(int, V) = 0, bool useDefault = true)
+    {
+      if (!tie(name.c_str(), SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
+        cout << "Failed to tie property " << name << " to indexed functions" << endl;
+      else if (debug_lvl & 0x20)
+        cout << name << endl;
+    }
+
+
+    /**
+     * Tie a property to a pair of object methods.
+     *
+     * Every time the property value is queried, the getter (if any) will
+     * be invoked; every time the property value is modified, the setter
+     * (if any) will be invoked.  The getter can be 0 to make the property
+     * unreadable, and the setter can be 0 to make the property
+     * unmodifiable.
+     *
+     * @param name The property name to tie (full path).
+     * @param obj The object whose methods should be invoked.
+     * @param getter The object's getter method, or 0 if the value is
+     *        unreadable.
+     * @param setter The object's setter method, or 0 if the value is
+     *        unmodifiable.
+     * @param useDefault true if the setter should be invoked with any existing
+     *        property value should be; false if the old value should be
+     *        discarded; defaults to true.
+     */
+    template <class T, class V> inline void
+    Tie (const string &name, T * obj, V (T::*getter)() const,
+           void (T::*setter)(V) = 0, bool useDefault = true)
+    {
+      if (!tie(name.c_str(), SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
+        cout << "Failed to tie property " << name << " to object methods" << endl;
+      else if (debug_lvl & 0x20)
+        cout << name << endl;
+    }
+
+    /**
+     * Tie a property to a pair of indexed object methods.
+     *
+     * Every time the property value is queried, the getter (if any) will
+     * be invoked with the index provided; every time the property value
+     * is modified, the setter (if any) will be invoked with the index
+     * provided.  The getter can be 0 to make the property unreadable, and
+     * the setter can be 0 to make the property unmodifiable.
+     *
+     * @param name The property name to tie (full path).
+     * @param obj The object whose methods should be invoked.
+     * @param index The integer argument to pass to the getter and
+     *        setter methods.
+     * @param getter The getter method, or 0 if the value is unreadable.
+     * @param setter The setter method, or 0 if the value is unmodifiable.
+     * @param useDefault true if the setter should be invoked with any existing
+     *        property value should be; false if the old value should be
+     *        discarded; defaults to true.
+     */
+    template <class T, class V> inline void
+    Tie (const string &name, T * obj, int index, V (T::*getter)(int) const,
+                         void (T::*setter)(int, V) = 0, bool useDefault = true)
+    {
+      if (!tie(name.c_str(), SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
+        cout << "Failed to tie property " << name << " to indexed object methods" << endl;
+      else if (debug_lvl & 0x20)
+        cout << name << endl;
+   }
+};
+}
+#endif // FGPROPERTYMANAGER_H
+
diff --git a/src/FDM/JSBSim/input_output/FGScript.cpp b/src/FDM/JSBSim/input_output/FGScript.cpp
new file mode 100755 (executable)
index 0000000..83e87f7
--- /dev/null
@@ -0,0 +1,422 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGScript.cpp
+ Author:       Jon S. Berndt
+ Date started: 12/21/01
+ Purpose:      Loads and runs JSBSim scripts.
+
+ ------------- 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 wraps up the simulation scripting routines.
+
+HISTORY
+--------------------------------------------------------------------------------
+12/21/01   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_IOSTREAM
+#  include STL_ITERATOR
+#else
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <iostream.h>
+#  else
+#    include <iostream>
+#  endif
+#  include <iterator>
+#endif
+
+#include "FGScript.h"
+#include "FGXMLParse.h"
+#include <initialization/FGTrim.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FGSCRIPT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+GLOBAL DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+// Constructor
+
+FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
+{
+  State = FDMExec->GetState();
+  PropertyManager=FDMExec->GetPropertyManager();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGScript::~FGScript()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGScript::LoadScript( string script )
+{
+  string aircraft="", initialize="", comparison = "", prop_name="";
+  Element *document=0, *element=0, *run_element=0, *when_element=0;
+  Element *parameter_element=0, *set_element=0;
+  bool result = false;
+  double dt = 0.0, value = 0.0;
+  FGXMLParse script_file_parser;
+  struct condition *newCondition;
+  ifstream script_file(script.c_str());
+
+  if ( !script_file ) return false;
+
+  readXML(script_file, script_file_parser);
+  document = script_file_parser.GetDocument();
+
+  if (document->GetName() != string("runscript")) {
+    cerr << "File: " << script << " is not a script file" << endl;
+    return false;
+  }
+
+  // read aircraft and initialization files
+
+  element = document->FindElement("use");
+  if (element) {
+    aircraft = element->GetAttributeValue("aircraft");
+    if (!aircraft.empty()) {
+      result = FDMExec->LoadModel(aircraft);
+      if (!result) return false;
+    } else {
+      cerr << "Aircraft must be specified first in script file." << endl;
+      return false;
+    }
+
+    element = document->FindNextElement("use");
+    initialize = element->GetAttributeValue("initialize");
+
+  } else {
+    cerr << "No \"use\" directives in the script file." << endl;
+    return false;
+  }
+
+  run_element = document->FindElement("run");
+
+  if (!run_element) {
+    cerr << "No \"run\" element found in script." << endl;
+    return false;
+  }
+
+  // Set sim timing
+
+  StartTime = run_element->GetAttributeValueAsNumber("start");
+  State->Setsim_time(StartTime);
+  EndTime   = run_element->GetAttributeValueAsNumber("end");
+  dt        = run_element->GetAttributeValueAsNumber("dt");
+  State->Setdt(dt);
+
+  // read "when" tests from script
+
+  when_element = run_element->FindElement("when");
+  while (when_element) { // "when" processing
+    newCondition = new struct condition();
+
+    // read parameters
+    parameter_element = when_element->FindElement("parameter");
+    while (parameter_element) {
+      prop_name = parameter_element->GetAttributeValue("name");
+      newCondition->TestParam.push_back( PropertyManager->GetNode(prop_name) );
+      value = parameter_element->GetAttributeValueAsNumber("value");
+      newCondition->TestValue.push_back(value);
+      comparison = parameter_element->GetAttributeValue("comparison");
+      newCondition->Comparison.push_back(comparison);
+      parameter_element = when_element->FindNextElement("parameter");
+    }
+
+    // read set definitions
+    set_element = when_element->FindElement("set");
+    while (set_element) {
+      prop_name = set_element->GetAttributeValue("name");
+      newCondition->SetParam.push_back( PropertyManager->GetNode(prop_name) );
+      value = set_element->GetAttributeValueAsNumber("value");
+      newCondition->SetValue.push_back(value);
+      newCondition->Triggered.push_back(false);
+      newCondition->OriginalValue.push_back(0.0);
+      newCondition->newValue.push_back(0.0);
+      newCondition->StartTime.push_back(0.0);
+      newCondition->EndTime.push_back(0.0);
+      string tempCompare = set_element->GetAttributeValue("type");
+      if      (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);
+      else if (tempCompare == "FG_BOOL")  newCondition->Type.push_back(FG_BOOL);
+      else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);
+      else                                newCondition->Type.push_back(FG_VALUE); // DEFAULT
+      tempCompare = set_element->GetAttributeValue("action");
+      if      (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);
+      else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);
+      else if (tempCompare == "FG_EXP")  newCondition->Action.push_back(FG_EXP);
+      else                               newCondition->Action.push_back(FG_STEP); // DEFAULT
+
+      if (set_element->GetAttributeValue("persistent") == "true")
+        newCondition->Persistent.push_back(true);
+      else
+        newCondition->Persistent.push_back(false); // DEFAULT
+
+      if (!set_element->GetAttributeValue("tc").empty())
+        newCondition->TC.push_back(set_element->GetAttributeValueAsNumber("tc"));
+      else
+        newCondition->TC.push_back(1.0); // DEFAULT
+
+      set_element = when_element->FindNextElement("set");
+    }
+    Conditions.push_back(*newCondition);
+    when_element = run_element->FindNextElement("when");
+  }
+
+  Debug(4);
+
+  FGInitialCondition *IC=FDMExec->GetIC();
+  if ( ! IC->Load( initialize )) {
+    cerr << "Initialization unsuccessful" << endl;
+    exit(-1);
+  }
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGScript::RunScript(void)
+{
+  vector <struct condition>::iterator iC = Conditions.begin();
+  bool truth = false;
+  bool WholeTruth = false;
+  unsigned i;
+
+  double currentTime = State->Getsim_time();
+  double newSetValue = 0;
+
+  if (currentTime > EndTime) return false;
+
+  while (iC < Conditions.end()) {
+    // determine whether the set of conditional tests for this condition equate
+    // to true
+    for (i=0; i<iC->TestValue.size(); i++) {
+           if (iC->Comparison[i] == "lt")
+              truth = iC->TestParam[i]->getDoubleValue() <  iC->TestValue[i];
+      else if (iC->Comparison[i] == "le")
+              truth = iC->TestParam[i]->getDoubleValue() <= iC->TestValue[i];
+      else if (iC->Comparison[i] == "eq")
+              truth = iC->TestParam[i]->getDoubleValue() == iC->TestValue[i];
+      else if (iC->Comparison[i] == "ge")
+              truth = iC->TestParam[i]->getDoubleValue() >= iC->TestValue[i];
+      else if (iC->Comparison[i] == "gt")
+              truth = iC->TestParam[i]->getDoubleValue() >  iC->TestValue[i];
+      else if (iC->Comparison[i] == "ne")
+              truth = iC->TestParam[i]->getDoubleValue() != iC->TestValue[i];
+      else
+              cerr << "Bad comparison" << endl;
+
+      if (i == 0) WholeTruth = truth;
+      else        WholeTruth = WholeTruth && truth;
+
+      if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false;
+    }
+
+    // if the conditions are true, do the setting of the desired parameters
+
+    if (WholeTruth) {
+      for (i=0; i<iC->SetValue.size(); i++) {
+        if ( ! iC->Triggered[i]) {
+          iC->OriginalValue[i] = iC->SetParam[i]->getDoubleValue();
+          switch (iC->Type[i]) {
+          case FG_VALUE:
+            iC->newValue[i] = iC->SetValue[i];
+            break;
+          case FG_DELTA:
+            iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i];
+            break;
+          case FG_BOOL:
+            iC->newValue[i] = iC->SetValue[i];
+            break;
+          default:
+            cerr << "Invalid Type specified" << endl;
+            break;
+          }
+          iC->Triggered[i] = true;
+          iC->StartTime[i] = currentTime;
+        }
+
+        double time_span = currentTime - iC->StartTime[i];
+        double value_span = iC->newValue[i] - iC->OriginalValue[i];
+
+        switch (iC->Action[i]) {
+        case FG_RAMP:
+          if (time_span <= iC->TC[i])
+            newSetValue = time_span/iC->TC[i] * value_span + iC->OriginalValue[i];
+          else
+            newSetValue = iC->newValue[i];
+          break;
+        case FG_STEP:
+          newSetValue = iC->newValue[i];
+          break;
+        case FG_EXP:
+          newSetValue = (1 - exp( -time_span/iC->TC[i] )) * value_span + iC->OriginalValue[i];
+          break;
+        default:
+          cerr << "Invalid Action specified" << endl;
+          break;
+        }
+        iC->SetParam[i]->setDoubleValue(newSetValue);
+      }
+    }
+    iC++;
+  }
+  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 FGScript::Debug(int from)
+{
+  unsigned int i;
+
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+    } else if (from == 3) {
+    } else if (from == 4)  { // print out script data
+      vector <struct condition>::iterator iterConditions = Conditions.begin();
+      int count=0;
+
+      cout << "\n  Script goes from " << StartTime << " to " << EndTime
+           << " with dt = " << State->Getdt() << endl << endl;
+
+      while (iterConditions < Conditions.end()) {
+        cout << "  Condition: " << count++ << endl;
+        cout << "    if (";
+
+        for (i=0; i<iterConditions->TestValue.size(); i++) {
+          if (i>0) cout << " and" << endl << "        ";
+          cout << "(" << iterConditions->TestParam[i]->GetName()
+                      << " " << iterConditions->Comparison[i] << " "
+                      << iterConditions->TestValue[i] << ")";
+        }
+        cout << ") then {";
+
+        for (i=0; i<iterConditions->SetValue.size(); i++) {
+          cout << endl << "      set " << iterConditions->SetParam[i]->GetName()
+               << " to " << iterConditions->SetValue[i];
+
+          switch (iterConditions->Type[i]) {
+          case FG_VALUE:
+            cout << " (constant";
+            break;
+          case FG_DELTA:
+            cout << " (delta";
+            break;
+          case FG_BOOL:
+            cout << " (boolean";
+            break;
+          default:
+            cout << " (unspecified type";
+          }
+
+          switch (iterConditions->Action[i]) {
+          case FG_RAMP:
+            cout << " via ramp";
+            break;
+          case FG_STEP:
+            cout << " via step";
+            break;
+          case FG_EXP:
+            cout << " via exponential approach";
+            break;
+          default:
+            cout << " via unspecified action";
+          }
+
+          if (!iterConditions->Persistent[i]) cout << endl
+                             << "                              once";
+          else cout << endl
+                             << "                              repeatedly";
+
+          if (iterConditions->Action[i] == FG_RAMP ||
+              iterConditions->Action[i] == FG_EXP) cout << endl
+                             << "                              with time constant "
+                             << iterConditions->TC[i];
+        }
+        cout << ")" << endl << "    }" << endl << endl;
+
+        iterConditions++;
+      }
+
+      cout << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGScript" << endl;
+    if (from == 1) cout << "Destroyed:    FGScript" << 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/input_output/FGScript.h b/src/FDM/JSBSim/input_output/FGScript.h
new file mode 100644 (file)
index 0000000..7b4587a
--- /dev/null
@@ -0,0 +1,197 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGScript.h
+ Author:       Jon Berndt
+ Date started: 12/21/2001
+
+ ------------- Copyright (C) 2001  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/21/01   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGSCRIPT_HEADER_H
+#define FGSCRIPT_HEADER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGJSBBase.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+#include <vector>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FGSCRIPT "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates the JSBSim scripting capability.
+    <h4>Scripting support provided via FGScript.</h4>
+
+    <p>There is simple scripting support provided in the FGScript
+    class. Commands are specified using the <em>Simple Scripting
+    Directives for JSBSim</em> (SSDJ). The script file is in XML
+    format. A test condition (or conditions) can be set up in the
+    script and when the condition evaluates to true, the specified
+    action[s] is/are taken. A test condition can be <em>persistent</em>,
+    meaning that if a test condition evaluates to true, then passes
+    and evaluates to false, the condition is reset and may again be
+    triggered. When the set of tests evaluates to true for a given
+    condition, an item may be set to another value. This value might
+    be a boolean, a value, or a delta value, and the change from the
+    current value to the new value can be either via a step function,
+    a ramp, or an exponential approach. The speed of a ramp or
+    approach is specified via the time constant. Here is the format
+    of the script file:</p>
+
+    <pre><strong>&lt;?xml version=&quot;1.0&quot;?&gt;
+    &lt;runscript name=&quot;C172-01A&quot;&gt;
+
+    &lt;!--
+    This run is for testing C172 runs
+    --&gt;
+
+    &lt;use aircraft=&quot;c172&quot;&gt;
+    &lt;use initialize=&quot;reset00&quot;&gt;
+
+    &lt;run start=&quot;0.0&quot; end=&quot;4.5&quot; dt=&quot;0.05&quot;&gt;
+      &lt;when&gt;
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;0.25&quot;&gt;
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;0.50&quot;&gt;
+        &lt;set name=&quot;FG_AILERON_CMD&quot; type=&quot;FG_VALUE&quot; value=&quot;0.25&quot;
+        action=&quot;FG_STEP&quot; persistent=&quot;false&quot; tc =&quot;0.25&quot;&gt;
+      &lt;/when&gt;
+      &lt;when&gt;
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;0.5&quot;&gt;
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;1.5&quot;&gt;
+        &lt;set name=&quot;FG_AILERON_CMD&quot; type=&quot;FG_DELTA&quot; value=&quot;0.5&quot;
+        action=&quot;FG_EXP&quot; persistent=&quot;false&quot; tc =&quot;0.5&quot;&gt;
+      &lt;/when&gt;
+      &lt;when&gt;
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;1.5&quot;&gt;
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;2.5&quot;&gt;
+        &lt;set name=&quot;FG_RUDDER_CMD&quot; type=&quot;FG_DELTA&quot; value=&quot;0.5&quot;
+        action=&quot;FG_RAMP&quot; persistent=&quot;false&quot; tc =&quot;0.5&quot;&gt;
+      &lt;/when&gt;
+    &lt;/run&gt;
+
+    &lt;/runscript&gt;</strong></pre>
+
+    <p>The first line must always be present. The second line
+    identifies this file as a script file, and gives a descriptive
+    name to the script file. Comments are next, delineated by the
+    &lt;!-- and --&gt; symbols. The aircraft and initialization files
+    to be used are specified in the &quot;use&quot; lines. Next,
+    comes the &quot;run&quot; section, where the conditions are
+    described in &quot;when&quot; clauses.</p>
+    @author Jon S. Berndt
+    @version "$Id$"
+
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGScript : public FGJSBBase
+{
+public:
+  /// Default constructor
+  FGScript(FGFDMExec* exec);
+
+  /// Default destructor
+  ~FGScript();
+
+  /** Loads a script to drive JSBSim (usually in standalone mode).
+      The language is the Simple Script Directives for JSBSim (SSDJ).
+      @param script the filename (including path name, if any) for the script.
+      @return true if successful */
+  bool LoadScript( string script );
+
+  /** This function is called each pass through the executive Run() method IF
+      scripting is enabled. 
+      @return false if script should exit (i.e. if time limits are violated */
+  bool RunScript(void);
+
+private:
+  enum eAction {
+    FG_RAMP  = 1,
+    FG_STEP  = 2,
+    FG_EXP   = 3
+  };
+
+  enum eType {
+    FG_VALUE = 1,
+    FG_DELTA = 2,
+    FG_BOOL  = 3
+  };
+
+  struct condition {
+    vector <FGPropertyManager*>  TestParam;
+    vector <FGPropertyManager*>  SetParam;
+    vector <double>  TestValue;
+    vector <double>  SetValue;
+    vector <string>  Comparison;
+    vector <double>  TC;
+    vector <bool>    Persistent;
+    vector <eAction> Action;
+    vector <eType>   Type;
+    vector <bool>    Triggered;
+    vector <double>  newValue;
+    vector <double>  OriginalValue;
+    vector <double>  StartTime;
+    vector <double>  EndTime;
+
+    condition() {
+    }
+  };
+
+  bool Scripted;
+
+  string  ScriptName;
+  double  StartTime;
+  double  EndTime;
+  vector <struct condition> Conditions;
+
+  FGFDMExec* FDMExec;
+  FGState* State;
+  FGPropertyManager* PropertyManager;
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.cpp b/src/FDM/JSBSim/input_output/FGXMLElement.cpp
new file mode 100755 (executable)
index 0000000..8b21b01
--- /dev/null
@@ -0,0 +1,417 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Author:       Jon Berndt
+ Date started: 09/28/2004
+ Purpose:      XML element class
+ Called by:    FGXMLParse
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGXMLElement.h"
+#ifdef FGFS
+#  ifndef __BORLANDC__
+#    include <simgear/compiler.h>
+#  endif
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <cmath>
+#    include <cstdlib>
+#  else
+#    include <math.h>
+#    include <stdlib.h>
+#  endif
+#else
+#  if defined (sgi) && !defined(__GNUC__)
+#    include <math.h>
+#    include <stdlib.h>
+#  else
+#    include <cmath>
+#    include <cstdlib>
+#  endif
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_XMLELEMENT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+Element::Element(string nm)
+{
+  name   = nm;
+  parent = 0L;
+  element_index = 0;
+
+  // convert ["from"]["to"] = factor, so: from * factor = to
+  convert["M"]["FT"] = 3.2808399;
+  convert["FT"]["M"] = 1.0/convert["M"]["FT"];
+  convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
+  convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
+  convert["FT"]["IN"] = 12.0;
+  convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
+  convert["LBS"]["KG"] = 0.45359237;
+  convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
+  convert["SLUG*FT2"]["KG*M2"] = 1.35594;
+  convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
+  convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
+  convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
+  convert["LBS/FT"]["N/M"] = 14.5939;
+  convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
+  convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
+  convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
+  convert["WATTS"]["HP"] = 0.001341022;
+  convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
+  convert["N"]["LBS"] = 0.22482;
+  convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
+  convert["KTS"]["FT/SEC"] = 1.68781;
+  convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
+  convert["FT*LBS"]["N*M"] = 1.35581795;
+  convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
+
+  convert["M"]["M"] = 1.00;
+  convert["FT"]["FT"] = 1.00;
+  convert["IN"]["IN"] = 1.00;
+  convert["IN3"]["IN3"] = 1.00;
+  convert["DEG"]["DEG"] = 1.00;
+  convert["RAD"]["RAD"] = 1.00;
+  convert["M2"]["M2"] = 1.00;
+  convert["FT2"]["FT2"] = 1.00;
+  convert["KG*M2"]["KG*M2"] = 1.00;
+  convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
+  convert["KG"]["KG"] = 1.00;
+  convert["LBS"]["LBS"] = 1.00;
+  convert["LBS/FT"]["LBS/FT"] = 1.00;
+  convert["LBS/SEC"]["LBS/SEC"] = 1.00;
+  convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
+  convert["N/M"]["N/M"] = 1.00;
+  convert["N/M/SEC"]["N/M/SEC"] = 1.00;
+  convert["PSI"]["PSI"] = 1.00;
+  convert["PSF"]["PSF"] = 1.00;
+  convert["INHG"]["INHG"] = 1.00;
+  convert["HP"]["HP"] = 1.00;
+  convert["N"]["N"] = 1.00;
+  convert["WATTS"]["WATTS"] = 1.00;
+  convert["LBS/SEC"]["LBS/SEC"] = 1.00;
+  convert["FT/SEC"]["FT/SEC"] = 1.00;
+  convert["KTS"]["KTS"] = 1.00;
+  convert["FT*LBS"]["FT*LBS"] = 1.00;
+  convert["N*M"]["N*M"] = 1.00;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Element::~Element(void)
+{
+  for (int i=0; i<children.size(); i++) delete children[i];
+  data_lines.clear();
+  attributes.clear();
+  attribute_key.clear();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string Element::GetAttributeValue(string attr)
+{
+  int select=-1;
+  for (int i=0; i<attribute_key.size(); i++) {
+    if (attribute_key[i] == attr) select = i;
+  }
+  if (select < 0) return string("");
+  else return attributes[attr];
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double Element::GetAttributeValueAsNumber(string attr)
+{
+  string attribute = GetAttributeValue(attr);
+
+  if (attribute.empty()) return 99e99;
+  else return (atof(attribute.c_str()));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Element* Element::GetElement(int el)
+{
+  if (children.size() > el) {
+    element_index = el;
+    return children[el];
+  }
+  else {
+    element_index = 0;
+    return 0L;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Element* Element::GetNextElement(void)
+{
+  if (children.size() > element_index+1) {
+    element_index++;
+    return children[element_index];
+  } else {
+    element_index = 0;
+    return 0L;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string Element::GetDataLine(int i)
+{
+  if (data_lines.size() > 0) return data_lines[i];
+  else return string("");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double Element::GetDataAsNumber(void)
+{
+  if (data_lines.size() == 1) {
+    return atof(data_lines[0].c_str());
+  } else {
+    return 99e99;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+int Element::GetNumElements(string element_name)
+{
+  int number_of_elements=0;
+  Element* el=FindElement(element_name);
+  while (el) {
+    number_of_elements++;
+    el=FindNextElement(element_name);
+  }
+  return number_of_elements;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Element* Element::FindElement(string el)
+{
+  if (el.empty() && children.size() >= 1) {
+    element_index = 1;
+    return children[0];
+  }
+  for (int i=0; i<children.size(); i++) {
+    if (el == children[i]->GetName()) {
+      element_index = i+1;
+      return children[i];
+    }
+  }
+  element_index = 0;
+  return 0L;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Element* Element::FindNextElement(string el)
+{
+  if (el.empty()) {
+    if (element_index < children.size()) {
+      return children[element_index++];
+    } else {
+      element_index = 0;
+      return 0L;
+    }
+  }
+  for (int i=element_index; i<children.size(); i++) {
+    if (el == children[i]->GetName()) {
+      element_index = i+1;
+      return children[i];
+    }
+  }
+  element_index = 0;
+  return 0L;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double Element::FindElementValueAsNumber(string el)
+{
+  Element* element = FindElement(el);
+  if (element) {
+    return element->GetDataAsNumber();
+  } else {
+    return 99e99;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string Element::FindElementValue(string el)
+{
+  Element* element = FindElement(el);
+  if (element) {
+    return element->GetDataLine();
+  } else {
+    return "";
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
+{
+  Element* element = FindElement(el);
+  double value;
+  string supplied_units="";
+
+  if (element) {
+     value = element->GetDataAsNumber();
+     supplied_units = element->GetAttributeValue("unit");
+     if (!supplied_units.empty()) {
+       if (convert.find(supplied_units) != convert.end()) {
+         if (convert[supplied_units].find(target_units) != convert[supplied_units].end()) {
+           value *= convert[supplied_units][target_units];
+         } else {
+           cerr << endl << "Target unit: \"" << target_units << "\" does not exist (typo?). Add new unit"
+                << " conversion in FGXMLElement.cpp." << endl;
+           exit(-1);
+         }
+       } else {
+         cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
+              << " conversion in FGXMLElement.cpp." << endl;
+         exit(-1);
+       }
+     }
+  } else {
+    return 99e99;
+  }
+  return value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double Element::FindElementValueAsNumberConvertFromTo( string el,
+                                                       string supplied_units,
+                                                       string target_units)
+{
+  Element* element = FindElement(el);
+  double value;
+
+  if (element) {
+     value = element->GetDataAsNumber();
+     if (!supplied_units.empty()) {
+       if (convert.find(supplied_units) != convert.end()) {
+         if (convert[supplied_units].find(target_units) != convert[supplied_units].end()) {
+           value *= convert[supplied_units][target_units];
+         } else {
+           cerr << endl << "Target unit: \"" << target_units << "\" does not exist (typo?). Add new unit"
+                << " conversion in FGXMLElement.cpp." << endl;
+           exit(-1);
+         }
+       } else {
+         cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
+              << " conversion in FGXMLElement.cpp." << endl;
+         exit(-1);
+       }
+     }
+  } else {
+    return 99e99;
+  }
+  return value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
+{
+  FGColumnVector3 triplet;
+  Element* item;
+  double value=0.0;
+  string supplied_units = GetAttributeValue("unit");
+
+  item = FindElement("x");
+  if (!item) item = FindElement("roll");
+  if (item) {
+    value = item->GetDataAsNumber();
+    if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
+  } else {
+    value = 0.0;
+    cerr << "Could not find an X triplet item for this column vector." << endl;
+  }
+  triplet(1) = value;
+
+  item = FindElement("y");
+  if (!item) item = FindElement("pitch");
+  if (item) {
+    value = item->GetDataAsNumber();
+    if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
+  } else {
+    value = 0.0;
+    cerr << "Could not find a Y triplet item for this column vector." << endl;
+  }
+  triplet(2) = value;
+
+  item = FindElement("z");
+  if (!item) item = FindElement("yaw");
+  if (item) {
+    value = item->GetDataAsNumber();
+    if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
+  } else {
+    value = 0.0;
+    cerr << "Could not find a Z triplet item for this column vector." << endl;
+  }
+  triplet(3) = value;
+
+  return triplet;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void Element::Print(int level)
+{
+  int i, spaces;
+
+  level+=2;
+  for (int spaces=0; spaces<=level; spaces++) cout << " "; // format output
+  cout << "Element Name: " << name;
+  for (int i=0; i<attributes.size(); i++) {
+    cout << "  " << attribute_key[i] << " = " << attributes[attribute_key[i]];
+  }
+  cout << endl;
+  for (i=0; i<data_lines.size(); i++) {
+    for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
+    cout << data_lines[i] << endl;
+  }
+  for (i=0; i<children.size(); i++) {
+    children[i]->Print(level);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void Element::AddAttribute(string name, string value)
+{
+  attribute_key.push_back(name);
+  attributes[name] = value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void Element::AddData(string d)
+{
+  int string_start = d.find_first_not_of(" ");
+  if (string_start > 0) d.erase(0,string_start-1);
+  data_lines.push_back(d);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+} // end namespace JSBSim
diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.h b/src/FDM/JSBSim/input_output/FGXMLElement.h
new file mode 100755 (executable)
index 0000000..8248fb8
--- /dev/null
@@ -0,0 +1,354 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ File:         FGXMLElement.h
+ Author:       Jon S. Berndt
+ Date started: 9/28/04
+
+ ------------- Copyright (C) 2004  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.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef XMLELEMENT_H
+#define XMLELEMENT_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <string>
+#    include <vector>
+#    include <iostream>
+#    include <map>
+#  else
+#    include <vector.h>
+#    include <string>
+#    include <iostream.h>
+#    include <map.h>
+#  endif
+#else
+#  include <string>
+#  include <map>
+#  include <iostream>
+#  include <vector>
+   using std::string;
+   using std::map;
+   using std::vector;
+   using std::cout;
+   using std::endl;
+#endif
+   using std::string;
+   using std::map;
+   using std::vector;
+   using std::cout;
+   using std::endl;
+
+#include <math/FGColumnVector3.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_XMLELEMENT "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates an XML element.
+    This class handles the creation, storage, and manipulation of XML elements.
+    This class also can convert supplied values as follows:
+
+    convert ["from"]["to"] = factor, so: from * factor = to
+    - convert["M"]["FT"] = 3.2808399;
+    - convert["FT"]["M"] = 1.0/convert["M"]["FT"];
+    - convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
+    - convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
+    - convert["FT"]["IN"] = 12.0;
+    - convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
+    - convert["LBS"]["KG"] = 0.45359237;
+    - convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
+    - convert["SLUG*FT2"]["KG*M2"] = 1.35594;
+    - convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
+    - convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
+    - convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
+    - convert["LBS/FT"]["N/M"] = 14.5939;
+    - convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
+    - convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
+    - convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
+    - convert["WATTS"]["HP"] = 0.001341022;
+    - convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
+    - convert["N"]["LBS"] = 0.22482;
+    - convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
+    - convert["KTS"]["FT/SEC"] = ktstofps;
+
+    - convert["M"]["M"] = 1.00;
+    - convert["FT"]["FT"] = 1.00;
+    - convert["IN"]["IN"] = 1.00;
+    - convert["DEG"]["DEG"] = 1.00;
+    - convert["RAD"]["RAD"] = 1.00;
+    - convert["M2"]["M2"] = 1.00;
+    - convert["FT2"]["FT2"] = 1.00;
+    - convert["KG*M2"]["KG*M2"] = 1.00;
+    - convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
+    - convert["KG"]["KG"] = 1.00;
+    - convert["LBS"]["LBS"] = 1.00;
+    - convert["LBS/FT"]["LBS/FT"] = 1.00;
+    - convert["N/M"]["N/M"] = 1.00;
+    - convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
+    - convert["N/M/SEC"]["N/M/SEC"] = 1.00;
+    - convert["PSI"]["PSI"] = 1.00;
+    - convert["INHG"]["INHG"] = 1.00;
+    - convert["HP"]["HP"] = 1.00;
+    - convert["N"]["N"] = 1.00;
+    - convert["WATTS"]["WATTS"] = 1.00;
+    - convert["KTS"]["KTS"] = 1.0;
+    - convert["FT/SEC"]["FT/SEC"] = 1.0;
+
+    Where:
+    - N = newtons
+    - M = meters
+    - M2 = meters squared
+    - KG = kilograms
+    - LBS = pounds force
+    - FT = feet
+    - FT2 = feet squared
+    - SEC = seconds
+    - SLUG = slug
+    - DEG = degrees
+    - RAD = radians
+    - WATTS = watts
+
+    @author Jon S. Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class Element {
+public:
+  /** Constructor
+      @param nm the name of this element (if given)
+      */
+  Element(string nm);
+  /// Destructor
+  ~Element(void);
+
+  /** Retrieves an attribute.
+      @param key specifies the attribute key to retrieve the value of.
+      @return the key value (as a string), or the empty string if no such
+              attribute exists. */
+  string GetAttributeValue(string key);
+
+  /** Retrieves an attribute value as a double precision real number.
+      @param key specifies the attribute key to retrieve the value of.
+      @return the key value (as a number), or the HUGE_VAL if no such
+              attribute exists. */
+  double GetAttributeValueAsNumber(string key);
+
+  /** Retrieves the element name.
+      @return the element name, or the empty string if no name has been set.*/
+  string GetName(void) {return name;}
+
+  /** Gets a line of data belonging to an element.
+      @param i the index of the data line to return (0 by default).
+      @return a string representing the data line requested, or the empty string
+              if none exists.*/
+  string GetDataLine(int i=0);
+
+  /// Returns the number of lines of data stored
+  int GetNumDataLines(void) {return data_lines.size();}
+
+  /// Returns the number of child elements for this element.
+  int GetNumElements(void) {return children.size();}
+
+  /// Returns the number of named child elements for this element.
+  int GetNumElements(string);
+
+  /** Converts the element data to a number.
+      This function attempts to convert the first (and presumably only) line of
+      data "owned" by the element into a real number. If there is not exactly one
+      line of data owned by the element, then HUGE_VAL is returned.
+      @return the numeric value of the data owned by the element.*/
+  double GetDataAsNumber(void);
+
+  /** Returns a pointer to the element requested by index.
+      This function also resets an internal counter to the index, so that
+      subsequent calls to GetNextElement() will return the following
+      elements sequentially, until the last element is reached. At that point,
+      GetNextElement() will return NULL.
+      @param el the index of the requested element (0 by default)
+      @return a pointer to the Element, or 0 if no valid element exists. */
+  Element* GetElement(int el=0);
+
+  /** Returns a pointer to the next element in the list.
+      The function GetElement() must be called first to be sure that this
+      function will return the correct element. The call to GetElement() resets
+      the internal counter to zero. Subsequent calls to GetNextElement() return
+      a pointer to subsequent elements in the list. When the final element is
+      reached, 0 is returned.
+      @return a pointer to the next Element in the sequence, or 0 if no valid
+              Element is present. */
+  Element* GetNextElement(void);
+
+  /** Returns a pointer to the parent of an element.
+      @return a pointer to the parent Element, or 0 if this is the top level Element. */
+  Element* GetParent(void) {return parent;}
+
+  /** Searches for a specified element.
+      Finds the first element that matches the supplied string, or simply the first
+      element if no search string is supplied. This function call resets the internal
+      element counter to the first element.
+      @param el the search string (empty string by default).
+      @return a pointer to the first element that matches the supplied search string. */
+  Element* FindElement(string el="");
+
+  /** Searches for the next element as specified.
+      This function would be called after FindElement() is first called (in order to
+      reset the internal counter). If no argument is supplied (or the empty string)
+      a pointer to the very next element is returned. Otherwise, the next occurence
+      of the named element is returned. If the end of the list is reached, 0 is
+      returned.
+      @param el the name of the next element to find.
+      @return the pointer to the found element, or 0 if no appropriate element us
+              found.*/
+  Element* FindNextElement(string el="");
+
+  /** Searches for the named element and returns the string data belonging to it.
+      This function allows the data belonging to a named element to be returned
+      as a string. If no element is found, the empty string is returned. If no
+      argument is supplied, the data string for the first element is returned.
+      @param el the name of the element being searched for (the empty string by
+      default)
+      @return the data value for the named element as a string, or the empty
+              string if the element cannot be found. */
+  string FindElementValue(string el="");
+
+  /** Searches for the named element and returns the data belonging to it as a number.
+      This function allows the data belonging to a named element to be returned
+      as a double. If no element is found, HUGE_VAL is returned. If no
+      argument is supplied, the data for the first element is returned.
+      @param el the name of the element being searched for (the empty string by
+      default)
+      @return the data value for the named element as a double, or HUGE_VAL if the
+              data is missing. */
+  double FindElementValueAsNumber(string el="");
+
+  /** Searches for the named element and converts and returns the data belonging to it.
+      This function allows the data belonging to a named element to be returned
+      as a double. If no element is found, HUGE_VAL is returned. If no
+      argument is supplied, the data for the first element is returned. Additionally,
+      this function converts the value from the units specified in the config file (via
+      the UNITS="" attribute in the element definition) to the native units used by
+      JSBSim itself, as specified by the target_units parameter. The currently
+      allowable unit conversions are seen in the source file FGXMLElement.cpp.
+      Also, see above in the main documentation for this class.
+      @param el the name of the element being searched for (the empty string by
+      default)
+      @param target_units the string representing the native units used by JSBSim
+             to which the value returned will be converted.
+      @return the unit-converted data value for the named element as a double,
+              or HUGE_VAL if the data is missing. */
+  double FindElementValueAsNumberConvertTo(string el, string target_units);
+
+  /** Searches for the named element and converts and returns the data belonging to it.
+      This function allows the data belonging to a named element to be returned
+      as a double. If no element is found, HUGE_VAL is returned. If no
+      argument is supplied, the data for the first element is returned. Additionally,
+      this function converts the value from the units specified in the supplied_units
+      parameter to the units specified in the target_units parameter. JSBSim itself,
+      as specified by the target_units parameter. The currently allowable unit
+      conversions are seen in the source file FGXMLElement.cpp. Also, see above
+      in the main documentation for this class.
+      @param el the name of the element being searched for (the empty string by
+      default)
+      @param supplied_units the string representing the units of the value as
+             supplied by the config file.
+      @param target_units the string representing the native units used by JSBSim
+             to which the value returned will be converted.
+      @return the unit-converted data value for the named element as a double,
+              or HUGE_VAL if the data is missing. */
+  double FindElementValueAsNumberConvertFromTo( string el,
+                                                string supplied_units,
+                                                string target_units);
+
+  /** Composes a 3-element column vector for the supplied location or orientation.
+      This function processes a LOCATION or ORIENTATION construct, returning a
+      filled-out 3-element column vector containing the X, Y, Z or ROLL, PITCH,
+      YAW elements found in the supplied element. If one of the mentioned components
+      is not found, that component is set to zero and a warning message is printed.
+      All three elements should be supplied.
+      @param target_units the string representing the native units used by JSBSim
+             to which the value returned will be converted.
+      @return a column vector object built from the LOCATION or ORIENT components. */
+  FGColumnVector3 FindElementTripletConvertTo( string target_units);
+
+  /** This function sets the value of the parent class attribute to the supplied
+      Element pointer.
+      @param p pointer to the parent Element. */
+  void SetParent(Element* p) {parent = p;}
+
+  /** Adds a child element to the list of children stored for this element.
+  *   @param el Child element to add. */
+  void AddChildElement(Element* el) {children.push_back(el);}
+
+  /** Stores an attribute belonging to this element.
+  *   @param name The string name of the attribute.
+  *   @param value The string value of the attribute. */
+  void AddAttribute(string name, string value);
+
+  /** Stores data belonging to this element.
+  *   @param d the data to store. */
+  void AddData(string d);
+
+  /** Prints the element.
+  *   Prints this element and calls the Print routine for child elements.
+  *   @param d The tab level. A level corresponds to a single space. */
+  void Print(int level=0);
+
+private:
+  string name;
+  map <string, string> attributes;
+  vector <string> data_lines;
+  vector <Element*> children;
+  vector <string> attribute_key;
+  Element *parent;
+  int element_index;
+  typedef map <string, map <string, double> > tMapConvert;
+  tMapConvert convert;
+};
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif
diff --git a/src/FDM/JSBSim/input_output/FGXMLParse.cpp b/src/FDM/JSBSim/input_output/FGXMLParse.cpp
new file mode 100755 (executable)
index 0000000..6be5bf9
--- /dev/null
@@ -0,0 +1,146 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGXMLParse.h
+ Author:       Jon Berndt
+ Date started: 08/20/2004
+ Purpose:      Config file read-in class and XML parser
+ Called by:    Various
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGXMLParse.h"
+#include <stdlib.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_XMLPARSE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGXMLParse.h"
+
+using namespace std;
+
+FGXMLParse::FGXMLParse(void)
+{
+  first_element_read = false;
+  current_element = document = 0L;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGXMLParse::~FGXMLParse(void)
+{
+  if (document) delete document;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::startXML(void)
+{
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::reset(void)
+{
+  if (document) delete document;
+  first_element_read = false;
+  current_element = document = 0L;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::endXML(void)
+{
+  // At this point, document should equal current_element ?
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::startElement (const char * name, const XMLAttributes &atts)
+{
+  string Name(name);
+  Element *temp_element;
+
+  working_string.erase();
+
+  if (!first_element_read) {
+    document = new Element(Name);
+    current_element = document;
+    first_element_read = true;
+  } else {
+    temp_element = new Element(Name);
+    temp_element->SetParent(current_element);
+    current_element->AddChildElement(temp_element);
+    current_element = temp_element;
+  }
+
+  if (current_element == 0L) {
+    cerr << "No current element read (no top-level element in XML file?)" << endl;
+    exit (-1);
+  }
+
+  for (int i=0; i<atts.size();i++) {
+    current_element->AddAttribute(atts.getName(i), atts.getValue(i));
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::endElement (const char * name)
+{
+  int size, pos;
+  string local_work_string;
+
+  while (!working_string.empty()) {
+     // clear leading newlines and spaces
+    while (working_string[0] == '\n' || working_string[0] == ' ')
+      working_string.erase(0,1);
+
+    // remove spaces (only) from end of string
+    size = working_string.size();
+    while (working_string[size-1] == ' ')
+    {
+      working_string.erase(size-1,1);
+      size = working_string.size();
+    }
+
+    if (!working_string.empty()) {
+      pos = working_string.find("\n");
+      if (pos != string::npos) local_work_string = working_string.substr(0,pos);
+      else local_work_string = working_string;
+      current_element->AddData(local_work_string);
+      working_string.erase(0, pos);
+    }
+  }
+
+  current_element = current_element->GetParent();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::data (const char * s, int length)
+{
+  working_string += string(s, length);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::pi (const char * target, const char * data)
+{
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGXMLParse::warning (const char * message, int line, int column)
+{
+  cerr << "Warning: " << message << " line: " << line << " column: " << column << endl;
+}
+
+} // end namespace JSBSim
diff --git a/src/FDM/JSBSim/input_output/FGXMLParse.h b/src/FDM/JSBSim/input_output/FGXMLParse.h
new file mode 100755 (executable)
index 0000000..a86cd6e
--- /dev/null
@@ -0,0 +1,106 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGXMLParse.h
+ Author:       Jon S. Berndt
+ Date started: 8/20/04
+
+ ------------- Copyright (C) 2004  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.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGXMLPARSE_H
+#define FGXMLPARSE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_STRING
+#else
+#  include <string>
+#  include <iostream>
+   using std::string;
+   using std::cout;
+   using std::cerr;
+   using std::endl;
+#endif
+
+#include "FGXMLElement.h"
+#include "simgear/xml/easyxml.hxx"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_XMLPARSE "$Id$"
+#define VALID_CHARS """`!@#$%^&*()_+`1234567890-={}[];':,.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates an XML parser based on the EasyXML parser from the SimGear library.
+    @author Jon S. Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGXMLParse : public XMLVisitor
+{
+public:
+  FGXMLParse(void);
+  virtual ~FGXMLParse(void);
+
+  Element* GetDocument(void) {return document;}
+
+  void startXML();
+  void endXML();
+  void startElement (const char * name, const XMLAttributes &atts);
+  void endElement (const char * name);
+  void data (const char * s, int length);
+  void pi (const char * target, const char * data);
+  void warning (const char * message, int line, int column);
+  void reset(void);
+
+private:
+  bool first_element_read;
+  mutable string working_string;
+  Element *document;
+  Element *current_element;
+};
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif
diff --git a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp
new file mode 100644 (file)
index 0000000..c9db20f
--- /dev/null
@@ -0,0 +1,340 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGfdmSocket.cpp
+ Author:       Jon S. Berndt
+ Date started: 11/08/99
+ Purpose:      Encapsulates a socket
+ Called by:    FGOutput, 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 excapsulates a socket for simple data writing
+
+HISTORY
+--------------------------------------------------------------------------------
+11/08/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGfdmSocket.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FDMSOCKET;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGfdmSocket::FGfdmSocket(string address, int port)
+{
+  sckt = sckt_in = size = 0;
+  connected = false;
+
+  #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+    WSADATA wsaData;
+    int wsaReturnCode;
+    wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
+    if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
+    else cout << "Winsock DLL not initialized ..." << endl;
+  #endif
+
+  if (address.find_first_not_of("0123456789.",0) != address.npos) {
+    if ((host = gethostbyname(address.c_str())) == NULL) {
+      cout << "Could not get host net address by name..." << endl;
+    }
+  } else {
+    if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) {
+      cout << "Could not get host net address by number..." << endl;
+    }
+  }
+
+  if (host != NULL) {
+    cout << "Got host net address..." << endl;
+    sckt = socket(AF_INET, SOCK_STREAM, 0);
+
+    if (sckt >= 0) {  // successful
+      memset(&scktName, 0, sizeof(struct sockaddr_in));
+      scktName.sin_family = AF_INET;
+      scktName.sin_port = htons(port);
+      memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
+      int len = sizeof(struct sockaddr_in);
+      if (connect(sckt, (struct sockaddr*)&scktName, len) == 0) {   // successful
+        cout << "Successfully connected to socket ..." << endl;
+        connected = true;
+      } else {                // unsuccessful
+        cout << "Could not connect to socket ..." << endl;
+      }
+    } else {          // unsuccessful
+      cout << "Could not create socket for FDM, error = " << errno << endl;
+    }
+  }
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGfdmSocket::FGfdmSocket(int port)
+{
+  size = 0;
+  connected = false;
+  unsigned long NoBlock = true;
+
+  #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+    WSADATA wsaData;
+    int wsaReturnCode;
+    wsaReturnCode = WSAStartup(MAKEWORD(1,1), &wsaData);
+    if (wsaReturnCode == 0) cout << "Winsock DLL loaded ..." << endl;
+    else cerr << "Winsock DLL not initialized ..." << endl;
+  #endif
+
+  sckt = socket(AF_INET, SOCK_STREAM, 0);
+
+  if (sckt >= 0) {  // successful
+    memset(&scktName, 0, sizeof(struct sockaddr_in));
+    scktName.sin_family = AF_INET;
+    scktName.sin_port = htons(port);
+//    memcpy(&scktName.sin_addr, host->h_addr_list[0], host->h_length);
+    int len = sizeof(struct sockaddr_in);
+    if (bind(sckt, (struct sockaddr*)&scktName, len) == 0) {   // successful
+      cout << "Successfully bound to socket ..." << endl;
+      if (listen(sckt, 5) >= 0) { // successful listen()
+        #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+          ioctlsocket(sckt, FIONBIO, &NoBlock);
+          sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
+        #else
+          ioctl(sckt, FIONBIO, &NoBlock);
+          sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
+        #endif
+      } else {
+        cerr << "Could not listen ..." << endl;
+      }
+      connected = true;
+    } else {                // unsuccessful
+      cerr << "Could not bind to socket ..." << endl;
+    }
+  } else {          // unsuccessful
+    cerr << "Could not create socket for FDM, error = " << errno << endl;
+  }
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGfdmSocket::~FGfdmSocket()
+{
+  #ifndef macintosh
+  if (sckt) shutdown(sckt,2);
+  if (sckt_in) shutdown(sckt_in,2);
+  #endif
+
+  #ifdef __BORLANDC__
+    WSACleanup();
+  #endif
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGfdmSocket::Receive(void)
+{
+  char buf[1024];
+  int len = sizeof(struct sockaddr_in);
+  int num_chars=0;
+  int total_chars = 0;
+  unsigned long NoBlock = true;
+  string data = ""; // todo: should allocate this with a standard size as a
+                    // class attribute and pass as a reference?
+
+  if (sckt_in <= 0) {
+    #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+      sckt_in = accept(sckt, (struct sockaddr*)&scktName, &len);
+    #else
+      sckt_in = accept(sckt, (struct sockaddr*)&scktName, (socklen_t*)&len);
+    #endif
+    if (sckt_in > 0) {
+      #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+         ioctlsocket(sckt_in, FIONBIO,&NoBlock);
+      #else
+         ioctl(sckt_in, FIONBIO, &NoBlock);
+      #endif
+      send(sckt_in, "Connected to JSBSim server\nJSBSim> ", 35, 0);
+    }
+  }
+
+  if (sckt_in > 0) {
+    while ((num_chars = recv(sckt_in, buf, 1024, 0)) > 0) {
+      data += string(buf).substr(0,num_chars);
+      total_chars += num_chars;
+    }
+
+#if defined(_MSC_VER)
+    // when nothing received and the error isn't "would block"
+    // then assume that the client has closed the socket.
+    if (num_chars == 0) {
+        DWORD err = WSAGetLastError ();
+        if (err != WSAEWOULDBLOCK) {
+            printf ("Socket Closed. back to listening\n");
+            closesocket (sckt_in);
+            sckt_in = -1;
+        }
+    }
+#endif
+  }
+
+  return data.substr(0, total_chars);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+int FGfdmSocket::Reply(string text)
+{
+  int num_chars_sent=0;
+
+  if (sckt_in >= 0) {
+    num_chars_sent = send(sckt_in, text.c_str(), text.size(), 0);
+    send(sckt_in, "JSBSim> ", 8, 0);
+  } else {
+    cerr << "Socket reply must be to a valid socket" << endl;
+    return -1;
+  }
+  return num_chars_sent;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGfdmSocket::Close(void)
+{
+  close(sckt_in);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGfdmSocket::Clear(void)
+{
+  buffer = "";
+  size = 0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGfdmSocket::Clear(string s)
+{
+  buffer = s + " ";
+  size = buffer.size();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGfdmSocket::Append(const char* item)
+{
+  if (size == 0) buffer += string(item);
+  else buffer += string(",") + string(item);
+  size++;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGfdmSocket::Append(double item)
+{
+  char s[25];
+
+  sprintf(s,"%12.7f",item);
+
+  if (size == 0) buffer += string(s);
+  else buffer += string(",") + string(s);
+  size++;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGfdmSocket::Append(long item)
+{
+  char s[25];
+
+  sprintf(s,"%12ld",item);
+
+  if (size == 0) buffer += string(s);
+  else buffer += string(",") + string(s);
+  size++;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGfdmSocket::Send(void)
+{
+  buffer += string("\n");
+  if ((send(sckt,buffer.c_str(),buffer.size(),0)) <= 0) {
+    perror("send");
+  } else {
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGfdmSocket::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: FGfdmSocket" << endl;
+    if (from == 1) cout << "Destroyed:    FGfdmSocket" << 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/input_output/FGfdmSocket.h b/src/FDM/JSBSim/input_output/FGfdmSocket.h
new file mode 100644 (file)
index 0000000..7eed2fe
--- /dev/null
@@ -0,0 +1,133 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGfdmSocket.h
+ Author:       Jon S. Berndt
+ Date started: 11/08/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/08/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGfdmSocket_H
+#define FGfdmSocket_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <stdio.h>
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_STRING
+#  include STL_IOSTREAM
+#  include STL_FSTREAM
+   SG_USING_STD(cout);
+   SG_USING_STD(endl);
+#else
+#  include <string>
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <iostream.h>
+#    include <fstream.h>
+#  else
+#    include <iostream>
+#    include <fstream>
+     using std::cout;
+     using std::endl;
+#  endif
+#endif
+
+#include <sys/types.h>
+#include "FGJSBBase.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+  #include <winsock.h>
+  #include <io.h>
+#else
+  #include <unistd.h>
+  #include <sys/socket.h>
+  #include <netinet/in.h>
+  #include <netdb.h>
+  #include <errno.h>
+  #include <sys/ioctl.h>
+#endif
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FDMSOCKET "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a socket object.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+using std::string;
+using std::cerr;
+
+class FGfdmSocket : public FGJSBBase
+{
+public:
+  FGfdmSocket(string, int);
+  FGfdmSocket(int);
+  ~FGfdmSocket();
+  void Send(void);
+  string Receive(void);
+  int Reply(string text);
+  void Append(const string s) {Append(s.c_str());}
+  void Append(const char*);
+  void Append(double);
+  void Append(long);
+  void Clear(void);
+  void Clear(string s);
+  void Close(void);
+  bool GetConnectStatus(void) {return connected;}
+
+private:
+  int sckt;
+  int sckt_in;
+  int size;
+  struct sockaddr_in scktName;
+  struct hostent *host;
+  string buffer;
+  bool connected;
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/input_output/Makefile.am b/src/FDM/JSBSim/input_output/Makefile.am
new file mode 100644 (file)
index 0000000..6fff1d2
--- /dev/null
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = libInputOutput.a
+
+libInputOutput_a_SOURCES = FGGroundCallback.cpp FGPropertyManager.cpp FGScript.cpp FGXMLElement.cpp FGXMLParse.cpp FGfdmSocket.cpp
+
+noinst_HEADERS = FGGroundCallback.h FGPropertyManager.h FGScript.h FGXMLElement.h FGXMLParse.h FGfdmSocket.h 
+
+INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
diff --git a/src/FDM/JSBSim/math/FGColumnVector3.cpp b/src/FDM/JSBSim/math/FGColumnVector3.cpp
new file mode 100644 (file)
index 0000000..0b0fa03
--- /dev/null
@@ -0,0 +1,155 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Module: FGColumnVector3.cpp
+Author: Originally by Tony Peden [formatted here (and broken??) by JSB]
+Date started: 1998
+Purpose: FGColumnVector3 class
+Called by: Various
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+HISTORY
+--------------------------------------------------------------------------------
+??/??/??   TP   Created
+03/16/2000 JSB  Added exception throwing
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGColumnVector3.h"
+#include <stdio.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_COLUMNVECTOR3;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGColumnVector3::FGColumnVector3(void)
+{
+  data[0] = data[1] = data[2] = 0.0;
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGColumnVector3::Dump(string delimeter) const
+{
+  char buffer[256];
+  sprintf(buffer, "%f%s%f%s%f", Entry(1), delimeter.c_str(), Entry(2), delimeter.c_str(), Entry(3));
+  return string(buffer);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ostream& operator<<(ostream& os, const FGColumnVector3& col)
+{
+  os << col(1) << " , " << col(2) << " , " << col(3);
+  return os;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3 FGColumnVector3::operator/(const double scalar) const
+{
+  if (scalar != 0.0)
+    return operator*( 1.0/scalar );
+
+  cerr << "Attempt to divide by zero in method \
+    FGColumnVector3::operator/(const double scalar), \
+    object " << data[0] << " , " << data[1] << " , " << data[2] << endl;
+  return FGColumnVector3();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGColumnVector3::operator/=(const double scalar)
+{
+  if (scalar != 0.0)
+    operator*=( 1.0/scalar );
+  else
+    cerr << "Attempt to divide by zero in method \
+      FGColumnVector3::operator/=(const double scalar), \
+      object " << data[0] << " , " << data[1] << " , " << data[2] << endl;
+
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGColumnVector3::Magnitude(void) const
+{
+  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) );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGColumnVector3::Normalize(void)
+{
+  double Mag = Magnitude();
+
+  if (Mag != 0.0)
+    operator*=( 1.0/Mag );
+
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3 FGColumnVector3::multElementWise(const FGColumnVector3& V) const
+{
+  return FGColumnVector3(Entry(1) * V(1), Entry(2) * V(2), Entry(3) * V(3));
+}
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+//    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 FGColumnVector3::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: FGColumnVector3" << endl;
+    if (from == 1) cout << "Destroyed:    FGColumnVector3" << 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;
+    }
+  }
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/math/FGColumnVector3.h b/src/FDM/JSBSim/math/FGColumnVector3.h
new file mode 100644 (file)
index 0000000..e0d01bf
--- /dev/null
@@ -0,0 +1,308 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Header: FGColumnVector3.h
+Author: Originally by Tony Peden [formatted and adapted here by Jon Berndt]
+Date started: Unknown
+
+HISTORY
+--------------------------------------------------------------------------------
+??/??/???? ??   Initial version and more.
+03/06/2004 MF   Rework, document and do much inlineing.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGCOLUMNVECTOR3_H
+#define FGCOLUMNVECTOR3_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);
+#else
+#  include <string>
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <fstream.h>
+#    include <iostream.h>
+#    include <math.h>
+#  else
+#    include <fstream>
+#    include <iostream>
+#    if defined(sgi) && !defined(__GNUC__)
+#      include <math.h>
+#    else
+#      include <cmath>
+#    endif
+     using std::ostream;
+     using std::istream;
+     using std::cerr;
+     using std::cout;
+     using std::endl;
+#    if !(defined(_MSC_VER) && _MSC_VER <= 1200)
+       using std::sqrt;
+#    endif
+#  endif
+   using std::string;
+#endif
+
+#include "FGJSBBase.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_COLUMNVECTOR3 "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** This class implements a 3 dimensional vector.
+    @author Jon S. Berndt, Tony Peden, et. al.
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGColumnVector3 : public FGJSBBase
+{
+public:
+  /** Default initializer.
+      Create a zero vector.   */
+  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) {
+    data[0] = X;
+    data[1] = Y;
+    data[2] = Z;
+    Debug(0);
+  }
+
+  /** Copy constructor.
+      @param v Vector which is used for initialization.
+      Create copy of the vector given in the argument.   */
+  FGColumnVector3(const FGColumnVector3& v) {
+    data[0] = v.data[0];
+    data[1] = v.data[1];
+    data[2] = v.data[2];
+    Debug(0);
+  }
+
+  /// Destructor.
+  ~FGColumnVector3(void) { Debug(1); }
+
+  /** 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]; }
+
+  /** Prints the contents of the vector
+      @param delimeter the item separator (tab or comma)
+      @return a string with the delimeter-separated contents of the vector  */
+  string Dump(string delimeter) const;
+
+  /** Assignment operator.
+      @param b source vector.
+      Copy the content of the vector given in the argument into *this.   */
+  FGColumnVector3& operator=(const FGColumnVector3& b) {
+    data[0] = b.data[0];
+    data[1] = b.data[1];
+    data[2] = b.data[2];
+    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 {
+    return FGColumnVector3(scalar*Entry(1), scalar*Entry(2), scalar*Entry(3));
+  }
+
+  /** 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.   */
+  FGColumnVector3 operator*(const FGColumnVector3& V) const {
+    return FGColumnVector3( Entry(2) * V(3) - Entry(3) * V(2),
+                            Entry(3) * V(1) - Entry(1) * V(3),
+                            Entry(1) * V(2) - Entry(2) * V(1) );
+  }
+
+  /// Addition operator.
+  FGColumnVector3 operator+(const FGColumnVector3& B) const {
+    return FGColumnVector3( Entry(1) + B(1), Entry(2) + B(2), Entry(3) + B(3) );
+  }
+
+  /// Subtraction operator.
+  FGColumnVector3 operator-(const FGColumnVector3& B) const {
+    return FGColumnVector3( Entry(1) - B(1), Entry(2) - B(2), Entry(3) - B(3) );
+  }
+
+  /// Subtract an other vector.
+  FGColumnVector3& operator-=(const FGColumnVector3 &B) {
+    Entry(1) -= B(1);
+    Entry(2) -= B(2);
+    Entry(3) -= B(3);
+    return *this;
+  }
+
+  /// Add an other vector.
+  FGColumnVector3& operator+=(const FGColumnVector3 &B) {
+    Entry(1) += B(1);
+    Entry(2) += B(2);
+    Entry(3) += B(3);
+    return *this;
+  }
+
+  /// Scale by a scalar.
+  FGColumnVector3& operator*=(const double scalar) {
+    Entry(1) *= scalar;
+    Entry(2) *= scalar;
+    Entry(3) *= scalar;
+    return *this;
+  }
+
+  /// Scale by a 1/scalar.
+  FGColumnVector3& operator/=(const double scalar);
+
+  void InitMatrix(void) { data[0] = data[1] = data[2] = 0.0; }
+  void InitMatrix(double a) { data[0] = data[1] = data[2] = a; }
+  void InitMatrix(double a, double b, double c) {
+    data[0]=a; data[1]=b; data[2]=c;
+  }
+
+  /** Length of the vector.
+      Compute and return the euclidean norm of this vector.   */
+  double Magnitude(void) const;
+
+  /** Length of the vector in a coordinate axis plane.
+      Compute and return the euclidean norm of this vector projected into
+      the coordinate axis plane idx1-idx2.   */
+  double Magnitude(int idx1, int idx2) const {
+    return sqrt( Entry(idx1)*Entry(idx1) +  Entry(idx2)*Entry(idx2) );
+  }
+
+  /** Normalize.
+      Normalize the vector to have the Magnitude() == 1.0. If the vector
+      is equal to zero it is left untouched.   */
+  FGColumnVector3& Normalize(void);
+
+  // ??? Is this something sensible ??
+  FGColumnVector3 multElementWise(const FGColumnVector3& V) const;
+
+  // little trick here.
+  struct AssignRef {
+    AssignRef(FGColumnVector3& r, int i) : Ref(r), idx(i) {}
+    AssignRef operator<<(const double ff) {
+      Ref.Entry(idx) = ff;
+      return AssignRef(Ref, idx+1);
+    }
+    FGColumnVector3& Ref;
+    int idx;
+  };
+  AssignRef operator<<(const double ff) {
+    Entry(1) = ff;
+    return AssignRef(*this, 2);
+  }
+
+private:
+  double data[3];
+
+  void Debug(int from);
+};
+
+/** Scalar multiplication.
+    @param scalar scalar value to multiply with.
+    @param A Vector to multiply.
+    Multiply the Vector with a scalar value.*/
+inline FGColumnVector3 operator*(double scalar, const FGColumnVector3& A) {
+  // use already defined operation.
+  return A*scalar;
+}
+
+/** Write vector to a stream.
+    @param os Stream to write to.
+    @param M Matrix to write.
+    Write the matrix to a stream.*/
+ostream& operator<<(ostream& os, const FGColumnVector3& col);
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/math/FGFunction.cpp b/src/FDM/JSBSim/math/FGFunction.cpp
new file mode 100755 (executable)
index 0000000..6a60e62
--- /dev/null
@@ -0,0 +1,257 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Module: FGFunction.cpp
+Author: Jon Berndt
+Date started: 8/25/2004
+Purpose: Stores various parameter types for functions
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <stdio.h>
+
+#include "FGFunction.h"
+#include "FGTable.h"
+#include "FGPropertyValue.h"
+#include "FGRealValue.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FUNCTION;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
+                                      : PropertyManager(propMan), Prefix(prefix)
+{
+  int i;
+  Element* element;
+  string operation, property_name;
+  int size = el->GetNumElements();
+  cached = false;
+  cachedValue = -HUGE_VAL;
+
+  Name = el->GetAttributeValue("name");
+  operation = el->GetName();
+  if (operation == string("function")) {
+    Type = eTopLevel;
+    bind();
+  } else if (operation == string("product")) {
+    Type = eProduct;
+  } else if (operation == string("difference")) {
+    Type = eDifference;
+  } else if (operation == string("sum")) {
+    Type = eSum;
+  } else if (operation == string("quotient")) {
+    Type = eQuotient;
+  } else if (operation == string("pow")) {
+    Type = ePow;
+  } else if (operation == string("abs")) {
+    Type = eAbs;
+  } else if (operation == string("sin")) {
+    Type = eSin;
+  } else if (operation == string("cos")) {
+    Type = eCos;
+  } else if (operation == string("tan")) {
+    Type = eTan;
+  } else if (operation == string("asin")) {
+    Type = eASin;
+  } else if (operation == string("acos")) {
+    Type = eACos;
+  } else if (operation == string("atan")) {
+    Type = eATan;
+  } else if (operation == string("atan2")) {
+    Type = eATan2;
+  } else if (operation != string("description")) {
+    cerr << "Bad operation " << operation << " detected in configuration file" << endl;
+  }
+
+  element = el->GetElement();
+  while (element) {
+    operation = element->GetName();
+
+    // data types
+    if (operation == string("property")) {
+      property_name = element->GetDataLine();
+      Parameters.push_back(new FGPropertyValue(PropertyManager->GetNode(property_name)));
+    } else if (operation == string("value")) {
+      Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
+    } else if (operation == string("table")) {
+      Parameters.push_back(new FGTable(PropertyManager, element));
+    // operations
+    } else if (operation == string("product") ||
+               operation == string("difference") ||
+               operation == string("sum") ||
+               operation == string("quotient") ||
+               operation == string("pow") ||
+               operation == string("abs") ||
+               operation == string("sin") ||
+               operation == string("cos") ||
+               operation == string("tan") ||
+               operation == string("asin") ||
+               operation == string("acos") ||
+               operation == string("atan") ||
+               operation == string("atan2"))
+    {
+      Parameters.push_back(new FGFunction(PropertyManager, element));
+    } else if (operation != string("description")) {
+      cerr << "Bad operation " << operation << " detected in configuration file" << endl;
+    }
+    element = el->GetNextElement();
+  }
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGFunction::~FGFunction(void)
+{
+  string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
+  PropertyManager->Untie(tmp);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFunction::cacheValue(bool cache)
+{
+  cached = false; // Must set cached to false prior to calling GetValue(), else
+                  // it will _never_ calculate the value;
+  if (cache) {
+    cachedValue = GetValue();
+    cached = true;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGFunction::GetValue(void) const
+{
+  int i;
+
+  if (cached) return cachedValue;
+
+  double temp = Parameters[0]->GetValue();
+
+  switch (Type) {
+  case eTopLevel:
+    break;
+  case eProduct:
+    for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
+    break;
+  case eDifference:
+    for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
+    break;
+  case eSum:
+    for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
+    break;
+  case eQuotient:
+    temp /= Parameters[1]->GetValue();
+    break;
+  case ePow:
+    temp = pow(temp,Parameters[1]->GetValue());
+    break;
+  case eAbs:
+    temp = abs(temp);
+    break;
+  case eSin:
+    temp = sin(temp);
+    break;
+  case eCos:
+    temp = cos(temp);
+    break;
+  case eTan:
+    temp = tan(temp);
+    break;
+  case eACos:
+    temp = acos(temp);
+    break;
+  case eASin:
+    temp = asin(temp);
+    break;
+  case eATan:
+    temp = atan(temp);
+    break;
+  case eATan2:
+    temp = atan2(temp, Parameters[1]->GetValue());
+    break;
+  default:
+    cerr << "Unknown function operation type" << endl;
+    break;
+  }
+
+  return temp;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGFunction::GetValueAsString(void) const
+{
+  char buffer[20];
+  string value;
+
+  sprintf(buffer,"%9.6f",GetValue());
+  value = string(buffer);
+  return value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFunction::bind(void)
+{
+  string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
+  PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGFunction::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      if (Type == eTopLevel)
+        cout << "    Function: " << Name << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
+    if (from == 1) cout << "Destroyed:    FGGroundReactions" << 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/math/FGFunction.h b/src/FDM/JSBSim/math/FGFunction.h
new file mode 100755 (executable)
index 0000000..3c4fddf
--- /dev/null
@@ -0,0 +1,75 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Header: FGFunction.h
+Author: Jon Berndt
+Date started: August 25 2004
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGFUNCTION_H
+#define FGFUNCTION_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <vector>
+#include <string>
+#include "FGParameter.h"
+#include <input_output/FGXMLElement.h>
+#include <input_output/FGPropertyManager.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FUNCTION "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+  /** Represents various types of parameters.
+      @author Jon Berndt
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DECLARATION: FGFunction
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGFunction : public FGParameter
+{
+public:
+
+  FGFunction(FGPropertyManager* propMan, Element* el, string prefix="");
+  ~FGFunction();
+
+  double GetValue(void) const;
+  string GetValueAsString(void) const;
+  string GetName(void) const {return Name;}
+  void cacheValue(bool);
+
+private:
+  vector <FGParameter*> Parameters;
+  FGPropertyManager* const PropertyManager;
+  bool cached;
+  string Prefix;
+  double cachedValue;
+  enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow,
+                     eAbs, eSin, eCos, eTan, eASin, eACos, eATan, eATan2} Type;
+  string Name;
+  void bind(void);
+  void Debug(int from);
+};
+
+} // namespace JSBSim
+
+#endif
diff --git a/src/FDM/JSBSim/math/FGLocation.cpp b/src/FDM/JSBSim/math/FGLocation.cpp
new file mode 100644 (file)
index 0000000..995c89e
--- /dev/null
@@ -0,0 +1,221 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 <input_output/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 = mECLoc.Magnitude(eX, eY);
+  // Check if we have zero radius.
+  // If so set it to 1, so that we can set a position
+  if (0.0 == mECLoc.Magnitude())
+    rtmp = 1.0;
+
+  // Fast return if we are on the north or south pole ...
+  if (rtmp == 0.0)
+    return;
+
+  mCacheValid = false;
+
+  mECLoc(eX) = rtmp*cos(longitude);
+  mECLoc(eY) = rtmp*sin(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 = mECLoc.Magnitude(eX, 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/math/FGLocation.h b/src/FDM/JSBSim/math/FGLocation.h
new file mode 100644 (file)
index 0000000..44aa969
--- /dev/null
@@ -0,0 +1,444 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 <input_output/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.
+
+    Note: The latitude is a GEOCENTRIC value. FlightGear
+    converts latitude to a geodetic value and uses that. In order to get best
+    matching relative to a map, geocentric latitude must be converted to geodetic.
+
+    @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.
+      @param lon longitude
+      @param lat GEOCENTRIC latitude
+      @param distance from center of earth to vehicle in feet*/
+  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
diff --git a/src/FDM/JSBSim/math/FGMatrix33.cpp b/src/FDM/JSBSim/math/FGMatrix33.cpp
new file mode 100644 (file)
index 0000000..0d42129
--- /dev/null
@@ -0,0 +1,391 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Module: FGMatrix33.cpp
+Author: Tony Peden, Jon Berndt, Mathias Frolich
+Date started: 1998
+Purpose: FGMatrix33 class
+Called by: Various
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+HISTORY
+--------------------------------------------------------------------------------
+??/??/??   TP   Created
+03/16/2000 JSB  Added exception throwing
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_MATRIX33;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33::FGMatrix33(void)
+{
+  data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
+    data[6] = data[7] = data[8] = 0.0;
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ostream& operator<<(ostream& os, const FGMatrix33& M)
+{
+  for (unsigned int i=1; i<=M.Rows(); i++) {
+    for (unsigned int j=1; j<=M.Cols(); j++) {
+      if (i == M.Rows() && j == M.Cols())
+        os << M(i,j);
+      else
+        os << M(i,j) << ", ";
+    }
+  }
+  return os;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+istream& operator>>(istream& is, FGMatrix33& M)
+{
+  for (unsigned int i=1; i<=M.Rows(); i++) {
+    for (unsigned int j=1; j<=M.Cols(); j++) {
+      is >> M(i,j);
+    }
+  }
+  return is;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGMatrix33::Determinant(void) const {
+  return Entry(1,1)*Entry(2,2)*Entry(3,3) + Entry(1,2)*Entry(2,3)*Entry(3,1)
+    + Entry(1,3)*Entry(2,1)*Entry(3,2) - Entry(1,3)*Entry(2,2)*Entry(3,1)
+    - Entry(1,2)*Entry(2,1)*Entry(3,3) - Entry(2,3)*Entry(3,2)*Entry(1,1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33 FGMatrix33::Inverse(void) const {
+  // Compute the inverse of a general matrix using Cramers rule.
+  // I guess googling for cramers rule gives tons of references
+  // for this. :)
+  double rdet = 1.0/Determinant();
+
+  double i11 = rdet*(Entry(2,2)*Entry(3,3)-Entry(2,3)*Entry(3,2));
+  double i21 = rdet*(Entry(2,3)*Entry(3,1)-Entry(2,1)*Entry(3,3));
+  double i31 = rdet*(Entry(2,1)*Entry(3,2)-Entry(2,2)*Entry(3,1));
+  double i12 = rdet*(Entry(1,3)*Entry(3,2)-Entry(1,2)*Entry(3,3));
+  double i22 = rdet*(Entry(1,1)*Entry(3,3)-Entry(1,3)*Entry(3,1));
+  double i32 = rdet*(Entry(1,2)*Entry(3,1)-Entry(1,1)*Entry(3,2));
+  double i13 = rdet*(Entry(1,2)*Entry(2,3)-Entry(1,3)*Entry(2,2));
+  double i23 = rdet*(Entry(1,3)*Entry(2,1)-Entry(1,1)*Entry(2,3));
+  double i33 = rdet*(Entry(1,1)*Entry(2,2)-Entry(1,2)*Entry(2,1));
+
+  return FGMatrix33( i11, i12, i13,
+                     i21, i22, i23,
+                     i31, i32, i33 );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMatrix33::InitMatrix(void)
+{
+  data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
+    data[6] = data[7] = data[8] = 0.0;
+}
+
+// *****************************************************************************
+// binary operators ************************************************************
+// *****************************************************************************
+
+FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const
+{
+  return FGMatrix33( Entry(1,1) - M(1,1),
+                     Entry(1,2) - M(1,2),
+                     Entry(1,3) - M(1,3),
+                     Entry(2,1) - M(2,1),
+                     Entry(2,2) - M(2,2),
+                     Entry(2,3) - M(2,3),
+                     Entry(3,1) - M(3,1),
+                     Entry(3,2) - M(3,2),
+                     Entry(3,3) - M(3,3) );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M)
+{
+  data[0] -= M.data[0];
+  data[1] -= M.data[1];
+  data[2] -= M.data[2];
+  data[3] -= M.data[3];
+  data[4] -= M.data[4];
+  data[5] -= M.data[5];
+  data[6] -= M.data[6];
+  data[7] -= M.data[7];
+  data[8] -= M.data[8];
+
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const
+{
+  return FGMatrix33( Entry(1,1) + M(1,1),
+                     Entry(1,2) + M(1,2),
+                     Entry(1,3) + M(1,3),
+                     Entry(2,1) + M(2,1),
+                     Entry(2,2) + M(2,2),
+                     Entry(2,3) + M(2,3),
+                     Entry(3,1) + M(3,1),
+                     Entry(3,2) + M(3,2),
+                     Entry(3,3) + M(3,3) );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)
+{
+  Entry(1,1) += M(1,1);
+  Entry(1,2) += M(1,2);
+  Entry(1,3) += M(1,3);
+  Entry(2,1) += M(2,1);
+  Entry(2,2) += M(2,2);
+  Entry(2,3) += M(2,3);
+  Entry(3,1) += M(3,1);
+  Entry(3,2) += M(3,2);
+  Entry(3,3) += M(3,3);
+
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33 FGMatrix33::operator*(const double scalar) const
+{
+  return FGMatrix33( scalar * Entry(1,1),
+                     scalar * Entry(1,2),
+                     scalar * Entry(1,3),
+                     scalar * Entry(2,1),
+                     scalar * Entry(2,2),
+                     scalar * Entry(2,3),
+                     scalar * Entry(3,1),
+                     scalar * Entry(3,2),
+                     scalar * Entry(3,3) );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33 operator*(double scalar, FGMatrix33 &M)
+{
+  return FGMatrix33( scalar * M(1,1),
+                     scalar * M(1,2),
+                     scalar * M(1,3),
+                     scalar * M(2,1),
+                     scalar * M(2,2),
+                     scalar * M(2,3),
+                     scalar * M(3,1),
+                     scalar * M(3,2),
+                     scalar * M(3,3) );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33& FGMatrix33::operator*=(const double scalar)
+{
+  Entry(1,1) *= scalar;
+  Entry(1,2) *= scalar;
+  Entry(1,3) *= scalar;
+  Entry(2,1) *= scalar;
+  Entry(2,2) *= scalar;
+  Entry(2,3) *= scalar;
+  Entry(3,1) *= scalar;
+  Entry(3,2) *= scalar;
+  Entry(3,3) *= scalar;
+
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const
+{
+  // FIXME: Make compiler friendlier
+  FGMatrix33 Product;
+
+  Product(1,1) = Entry(1,1)*M(1,1) + Entry(1,2)*M(2,1) + Entry(1,3)*M(3,1);
+  Product(1,2) = Entry(1,1)*M(1,2) + Entry(1,2)*M(2,2) + Entry(1,3)*M(3,2);
+  Product(1,3) = Entry(1,1)*M(1,3) + Entry(1,2)*M(2,3) + Entry(1,3)*M(3,3);
+  Product(2,1) = Entry(2,1)*M(1,1) + Entry(2,2)*M(2,1) + Entry(2,3)*M(3,1);
+  Product(2,2) = Entry(2,1)*M(1,2) + Entry(2,2)*M(2,2) + Entry(2,3)*M(3,2);
+  Product(2,3) = Entry(2,1)*M(1,3) + Entry(2,2)*M(2,3) + Entry(2,3)*M(3,3);
+  Product(3,1) = Entry(3,1)*M(1,1) + Entry(3,2)*M(2,1) + Entry(3,3)*M(3,1);
+  Product(3,2) = Entry(3,1)*M(1,2) + Entry(3,2)*M(2,2) + Entry(3,3)*M(3,2);
+  Product(3,3) = Entry(3,1)*M(1,3) + Entry(3,2)*M(2,3) + Entry(3,3)*M(3,3);
+
+  return Product;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M)
+{
+  // FIXME: Make compiler friendlier
+  double a,b,c;
+
+  a = Entry(1,1); b=Entry(1,2); c=Entry(1,3);
+  Entry(1,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
+  Entry(1,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
+  Entry(1,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
+
+  a = Entry(2,1); b=Entry(2,2); c=Entry(2,3);
+  Entry(2,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
+  Entry(2,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
+  Entry(2,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
+
+  a = Entry(3,1); b=Entry(3,2); c=Entry(3,3);
+  Entry(3,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
+  Entry(3,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
+  Entry(3,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
+
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33 FGMatrix33::operator/(const double scalar) const
+{
+  FGMatrix33 Quot;
+
+  if ( scalar != 0 ) {
+    double tmp = 1.0/scalar;
+    Quot(1,1) = Entry(1,1) * tmp;
+    Quot(1,2) = Entry(1,2) * tmp;
+    Quot(1,3) = Entry(1,3) * tmp;
+    Quot(2,1) = Entry(2,1) * tmp;
+    Quot(2,2) = Entry(2,2) * tmp;
+    Quot(2,3) = Entry(2,3) * tmp;
+    Quot(3,1) = Entry(3,1) * tmp;
+    Quot(3,2) = Entry(3,2) * tmp;
+    Quot(3,3) = Entry(3,3) * tmp;
+  } else {
+    MatrixException mE;
+    mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)";
+    throw mE;
+  }
+  return Quot;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33& FGMatrix33::operator/=(const double scalar)
+{
+  if ( scalar != 0 ) {
+    double tmp = 1.0/scalar;
+    Entry(1,1) *= tmp;
+    Entry(1,2) *= tmp;
+    Entry(1,3) *= tmp;
+    Entry(2,1) *= tmp;
+    Entry(2,2) *= tmp;
+    Entry(2,3) *= tmp;
+    Entry(3,1) *= tmp;
+    Entry(3,2) *= tmp;
+    Entry(3,3) *= tmp;
+  } else {
+    MatrixException mE;
+    mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)";
+    throw mE;
+  }
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMatrix33::T(void)
+{
+  for (unsigned int i=1; i<=3; i++) {
+    for (unsigned int j=i+1; j<=3; j++) {
+      double tmp = Entry(i,j);
+      Entry(i,j) = Entry(j,i);
+      Entry(j,i) = tmp;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const {
+  double tmp1 = v(1)*Entry(1,1);
+  double tmp2 = v(1)*Entry(2,1);
+  double tmp3 = v(1)*Entry(3,1);
+
+  tmp1 += v(2)*Entry(1,2);
+  tmp2 += v(2)*Entry(2,2);
+  tmp3 += v(2)*Entry(3,2);
+
+  tmp1 += v(3)*Entry(1,3);
+  tmp2 += v(3)*Entry(2,3);
+  tmp3 += v(3)*Entry(3,3);
+
+  return FGColumnVector3( tmp1, tmp2, tmp3 );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGMatrix33::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: FGMatrix33" << endl;
+    if (from == 1) cout << "Destroyed:    FGMatrix33" << 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/math/FGMatrix33.h b/src/FDM/JSBSim/math/FGMatrix33.h
new file mode 100644 (file)
index 0000000..dc68b73
--- /dev/null
@@ -0,0 +1,470 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Header: FGMatrix33.h
+Author: Tony Peden, Jon Berndt, Mathias Frolich
+Date started: Unknown
+
+HISTORY
+--------------------------------------------------------------------------------
+??/??/??   TP   Created
+03/16/2000 JSB  Added exception throwing
+03/06/2004 MF   Rework of the code to make it a bit compiler friendlier
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGMATRIX33_H
+#define FGMATRIX33_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);
+#else
+#  include <string>
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+     include <fstream.h>
+     include <iostream.h>
+#    include <math.h>
+#  else
+#    include <fstream>
+#    include <iostream>
+#    if defined(sgi) && !defined(__GNUC__)
+#      include <math.h>
+#    else
+#      include <cmath>
+#    endif
+     using std::ostream;
+     using std::istream;
+     using std::cerr;
+     using std::cout;
+     using std::endl;
+#  endif
+   using std::string;
+#endif
+
+#include "FGColumnVector3.h"
+#include "FGJSBBase.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_MATRIX33 "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGColumnVector3;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Exception convenience class.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DECLARATION: MatrixException
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class MatrixException : public FGJSBBase
+{
+public:
+  string Message;
+};
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+  /** Handles matrix math operations.
+      @author Tony Peden, Jon Berndt, Mathias Froelich
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DECLARATION: FGMatrix33
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGMatrix33 : public FGJSBBase
+{
+public:
+
+  enum {
+    eRows = 3,
+    eColumns = 3
+  };
+
+  /** Default initializer.
+
+      Create a zero matrix.
+   */
+  FGMatrix33(void);
+
+  /** Copy constructor.
+
+      @param M Matrix which is used for initialization.
+
+      Create copy of the matrix given in the argument.
+   */
+  FGMatrix33(const FGMatrix33& M) {
+    Entry(1,1) = M.Entry(1,1);
+    Entry(2,1) = M.Entry(2,1);
+    Entry(3,1) = M.Entry(3,1);
+    Entry(1,2) = M.Entry(1,2);
+    Entry(2,2) = M.Entry(2,2);
+    Entry(3,2) = M.Entry(3,2);
+    Entry(1,3) = M.Entry(1,3);
+    Entry(2,3) = M.Entry(2,3);
+    Entry(3,3) = M.Entry(3,3);
+
+    Debug(0);
+  }
+
+  /** Initialization by given values.
+
+      @param m11 value of the 1,1 Matrix element.
+      @param m12 value of the 1,2 Matrix element.
+      @param m13 value of the 1,3 Matrix element.
+      @param m21 value of the 2,1 Matrix element.
+      @param m22 value of the 2,2 Matrix element.
+      @param m23 value of the 2,3 Matrix element.
+      @param m31 value of the 3,1 Matrix element.
+      @param m32 value of the 3,2 Matrix element.
+      @param m33 value of the 3,3 Matrix element.
+
+      Create a matrix from the doubles given in the arguments.
+   */
+  FGMatrix33(double m11, double m12, double m13,
+             double m21, double m22, double m23,
+             double m31, double m32, double m33) {
+    Entry(1,1) = m11;
+    Entry(2,1) = m21;
+    Entry(3,1) = m31;
+    Entry(1,2) = m12;
+    Entry(2,2) = m22;
+    Entry(3,2) = m32;
+    Entry(1,3) = m13;
+    Entry(2,3) = m23;
+    Entry(3,3) = m33;
+
+    Debug(0);
+  }
+
+  /** Destructor.
+   */
+  ~FGMatrix33(void) { Debug(1); }
+
+  /** Read access the entries of the matrix.
+      @param row Row index.
+      @param col Column index.
+
+      @return the value of the matrix entry at the given row and
+      column indices. Indices are counted starting with 1.
+   */
+  double operator()(unsigned int row, unsigned int col) const {
+    return Entry(row, col);
+  }
+
+  /** Write access the entries of the matrix.
+      Note that the indices given in the arguments are unchecked.
+
+      @param row Row index.
+      @param col Column index.
+
+      @return a reference to the matrix entry at the given row and
+      column indices. Indices are counted starting with 1.
+   */
+  double& operator()(unsigned int row, unsigned int col) {
+    return Entry(row, col);
+  }
+
+  /** Read access the entries of the matrix.
+      This function is just a shortcut for the @ref double&
+      operator()(unsigned int row, unsigned int col) function. It is
+      used internally to access the elements in a more convenient way.
+
+      Note that the indices given in the arguments are unchecked.
+
+      @param row Row index.
+      @param col Column index.
+
+      @return the value of the matrix entry at the given row and
+      column indices. Indices are counted starting with 1.
+   */
+  double Entry(unsigned int row, unsigned int col) const {
+    return data[(col-1)*eRows+row-1];
+  }
+
+  /** Write access the entries of the matrix.
+      This function is just a shortcut for the @ref double&
+      operator()(unsigned int row, unsigned int col) function. It is
+      used internally to access the elements in a more convenient way.
+
+      Note that the indices given in the arguments are unchecked.
+
+      @param row Row index.
+      @param col Column index.
+
+      @return a reference to the matrix entry at the given row and
+      column indices. Indices are counted starting with 1.
+   */
+   double& Entry(unsigned int row, unsigned int col) {
+     return data[(col-1)*eRows+row-1];
+   }
+
+  /** Number of rows in the matrix.
+      @return the number of rows in the matrix.
+   */
+   unsigned int Rows(void) const { return eRows; }
+
+  /** Number of cloumns in the matrix.
+      @return the number of columns in the matrix.
+   */
+   unsigned int Cols(void) const { return eColumns; }
+
+  /** Transposed matrix.
+      This function only returns the transpose of this matrix. This matrix itself
+      remains unchanged.
+      @return the transposed matrix.
+   */
+  FGMatrix33 Transposed(void) const {
+    return FGMatrix33( Entry(1,1), Entry(2,1), Entry(3,1),
+                       Entry(1,2), Entry(2,2), Entry(3,2),
+                       Entry(1,3), Entry(2,3), Entry(3,3) );
+  }
+
+  /** Transposes this matrix.
+      This function only transposes this matrix. Nothing is returned.
+   */
+  void T(void);
+
+/** Initialize the matrix.
+    This function initializes a matrix to all 0.0.
+ */
+  void InitMatrix(void);
+
+/** Initialize the matrix.
+    This function initializes a matrix to user specified values.
+ */
+  void InitMatrix(double m11, double m12, double m13,
+                  double m21, double m22, double m23,
+                  double m31, double m32, double m33) {
+    Entry(1,1) = m11;
+    Entry(2,1) = m21;
+    Entry(3,1) = m31;
+    Entry(1,2) = m12;
+    Entry(2,2) = m22;
+    Entry(3,2) = m32;
+    Entry(1,3) = m13;
+    Entry(2,3) = m23;
+    Entry(3,3) = m33;
+  }
+
+  /** Determinant of the matrix.
+      @return the determinant of the matrix.
+   */
+  double Determinant(void) const;
+
+  /** Return if the matrix is invertible.
+      Checks and returns if the matrix is nonsingular and thus
+      invertible. This is done by simply computing the determinant and
+      check if it is zero. Note that this test does not cover any
+      instabilities caused by nearly singular matirces using finite
+      arithmetics. It only checks exact singularity.
+   */
+  bool Invertible(void) const { return 0.0 != Determinant(); }
+
+  /** Return the inverse of the matrix.
+      Computes and returns if the inverse of the matrix. It is computed
+      by Cramers Rule. Also there are no checks performed if the matrix
+      is invertible. If you are not sure that it really is check this
+      with the @ref Invertible() call before.
+   */
+  FGMatrix33 Inverse(void) const;
+
+  /** Assignment operator.
+
+      @param A source matrix.
+
+      Copy the content of the matrix given in the argument into *this.
+   */
+  FGMatrix33& operator=(const FGMatrix33& A) {
+    data[0] = A.data[0];
+    data[1] = A.data[1];
+    data[2] = A.data[2];
+    data[3] = A.data[3];
+    data[4] = A.data[4];
+    data[5] = A.data[5];
+    data[6] = A.data[6];
+    data[7] = A.data[7];
+    data[8] = A.data[8];
+    return *this;
+  }
+
+  /** Matrix vector multiplication.
+
+      @param v vector to multiply with.
+      @return matric vector product.
+
+      Compute and return the product of the current matrix with the
+      vector given in the argument.
+   */
+  FGColumnVector3 operator*(const FGColumnVector3& v) const;
+
+  /** Matrix subtraction.
+
+      @param B matrix to add to.
+      @return difference of the matrices.
+
+      Compute and return the sum of the current matrix and the matrix
+      B given in the argument.
+  */
+  FGMatrix33 operator-(const FGMatrix33& B) const;
+
+  /** Matrix addition.
+
+      @param B matrix to add to.
+      @return sum of the matrices.
+
+      Compute and return the sum of the current matrix and the matrix
+      B given in the argument.
+  */
+  FGMatrix33 operator+(const FGMatrix33& B) const;
+
+  /** Matrix product.
+
+      @param B matrix to add to.
+      @return product of the matrices.
+
+      Compute and return the product of the current matrix and the matrix
+      B given in the argument.
+  */
+  FGMatrix33 operator*(const FGMatrix33& B) const;
+
+  /** Multiply the matrix with a scalar.
+
+      @param scalar scalar factor to multiply with.
+      @return scaled matrix.
+
+      Compute and return the product of the current matrix with the
+      scalar value scalar given in the argument.
+  */
+  FGMatrix33 operator*(const double scalar) const;
+
+  /** Multiply the matrix with 1.0/scalar.
+
+      @param scalar scalar factor to divide through.
+      @return scaled matrix.
+
+      Compute and return the product of the current matrix with the
+      scalar value 1.0/scalar, where scalar is given in the argument.
+  */
+  FGMatrix33 operator/(const double scalar) const;
+
+  /** In place matrix subtraction.
+
+      @param B matrix to subtract.
+      @return reference to the current matrix.
+
+      Compute the diffence from the current matrix and the matrix B
+      given in the argument.
+  */
+  FGMatrix33& operator-=(const FGMatrix33 &B);
+
+  /** In place matrix addition.
+
+      @param B matrix to add.
+      @return reference to the current matrix.
+
+      Compute the sum of the current matrix and the matrix B
+      given in the argument.
+  */
+  FGMatrix33& operator+=(const FGMatrix33 &B);
+
+  /** In place matrix multiplication.
+
+      @param B matrix to multiply with.
+      @return reference to the current matrix.
+
+      Compute the product of the current matrix and the matrix B
+      given in the argument.
+  */
+  FGMatrix33& operator*=(const FGMatrix33 &B);
+
+  /** In place matrix scale.
+
+      @param scalar scalar value to multiply with.
+      @return reference to the current matrix.
+
+      Compute the product of the current matrix and the scalar value scalar
+      given in the argument.
+  */
+  FGMatrix33& operator*=(const double scalar);
+
+  /** In place matrix scale.
+
+      @param scalar scalar value to divide through.
+      @return reference to the current matrix.
+
+      Compute the product of the current matrix and the scalar value
+      1.0/scalar, where scalar is given in the argument.
+  */
+  FGMatrix33& operator/=(const double scalar);
+
+private:
+  double data[eRows*eColumns];
+
+  void Debug(int from);
+};
+
+/** Scalar multiplication.
+
+    @param scalar scalar value to multiply with.
+    @param A Matrix to multiply.
+
+    Multiply the Matrix with a scalar value.
+*/
+inline FGMatrix33 operator*(double scalar, const FGMatrix33& A) {
+  // use already defined operation.
+  return A*scalar;
+}
+
+/** Write matrix to a stream.
+
+    @param os Stream to write to.
+    @param M Matrix to write.
+
+    Write the matrix to a stream.
+*/
+ostream& operator<<(ostream& os, const FGMatrix33& M);
+
+/** Read matrix from a stream.
+
+    @param os Stream to read from.
+    @param M Matrix to initialize with the values from the stream.
+
+    Read matrix from a stream.
+*/
+istream& operator>>(istream& is, FGMatrix33& M);
+
+} // namespace JSBSim
+
+#endif
diff --git a/src/FDM/JSBSim/math/FGParameter.h b/src/FDM/JSBSim/math/FGParameter.h
new file mode 100755 (executable)
index 0000000..c970f7e
--- /dev/null
@@ -0,0 +1,55 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Header: FGParameter.h
+Author: Jon Berndt
+Date started: August 25 2004
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGPARAMETER_H
+#define FGPARAMETER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGJSBBase.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_PARAMETER "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+  /** Represents various types of parameters.
+      @author Jon Berndt
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DECLARATION: FGParameter
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGParameter : public FGJSBBase
+{
+public:
+
+  virtual double GetValue(void) const = 0;
+
+protected:
+};
+
+} // namespace JSBSim
+
+#endif
diff --git a/src/FDM/JSBSim/math/FGPropertyValue.cpp b/src/FDM/JSBSim/math/FGPropertyValue.cpp
new file mode 100755 (executable)
index 0000000..b0ae33e
--- /dev/null
@@ -0,0 +1,34 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Module: FGPropertyValue.cpp
+Author: Jon Berndt
+Date started: 12/10/2004
+Purpose: Stores property values
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGPropertyValue.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_PROPERTYVALUE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode) : PropertyManager(propNode)
+{
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGPropertyValue::GetValue(void) const
+{
+  return PropertyManager->getDoubleValue();
+}
+
+}
diff --git a/src/FDM/JSBSim/math/FGPropertyValue.h b/src/FDM/JSBSim/math/FGPropertyValue.h
new file mode 100755 (executable)
index 0000000..afce391
--- /dev/null
@@ -0,0 +1,60 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Header: FGPropertyValue.h
+Author: Jon Berndt
+Date started: December 10 2004
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGPROPERTYVALUE_H
+#define FGPROPERTYVALUE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGParameter.h"
+#include <input_output/FGPropertyManager.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_PROPERTYVALUE "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+  /** Represents a property value
+      @author Jon Berndt
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DECLARATION: FGPropertyValue
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGPropertyValue : public FGParameter
+{
+public:
+
+  FGPropertyValue(FGPropertyManager* propNode);
+  ~FGPropertyValue() {};
+
+  double GetValue(void) const;
+
+private:
+  FGPropertyManager* PropertyManager;
+};
+
+} // namespace JSBSim
+
+#endif
diff --git a/src/FDM/JSBSim/math/FGQuaternion.cpp b/src/FDM/JSBSim/math/FGQuaternion.cpp
new file mode 100644 (file)
index 0000000..55edcf8
--- /dev/null
@@ -0,0 +1,240 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 {
+  double norm = Magnitude();
+  if (norm == 0.0)
+    return FGQuaternion::zero();
+  double rnorm = 1.0/norm;
+
+  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 rnorm*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/math/FGQuaternion.h b/src/FDM/JSBSim/math/FGQuaternion.h
new file mode 100644 (file)
index 0000000..a23ced7
--- /dev/null
@@ -0,0 +1,494 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 <input_output/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);
+
+  /** Initializer by one euler angle.
+      Initialize the quaternion with the single euler angle where its index
+      is given in the first argument.
+      @param idx Index of the euler angle to initialize
+      @param angle The euler angle in radians  */
+  FGQuaternion(int idx, double angle)
+    : mCacheValid(false) {
+    double angle2 = 0.5*angle;
+
+    double Sangle2 = sin(angle2);
+    double Cangle2 = cos(angle2);
+
+    if (idx == ePhi) {
+      Entry(1) = Cangle2;
+      Entry(2) = Sangle2;
+      Entry(3) = 0.0;
+      Entry(4) = 0.0;
+
+    } else if (idx == eTht) {
+      Entry(1) = Cangle2;
+      Entry(2) = 0.0;
+      Entry(3) = Sangle2;
+      Entry(4) = 0.0;
+
+    } else {
+      Entry(1) = Cangle2;
+      Entry(2) = 0.0;
+      Entry(3) = 0.0;
+      Entry(4) = Sangle2;
+
+    }
+  }
+
+  /// 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(void) const { ComputeDerived(); return mT; }
+
+  /** Backward transformation matrix.
+      @return a reference to the inverse transformation/rotation matrix
+      corresponding to this quaternion rotation.  */
+  const FGMatrix33& GetTInv(void) 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(void) const {
+    ComputeDerived();
+    return mEulerAngles;
+  }
+
+  /** Retrieves the Euler angles.
+      @param i the euler angle index.
+      @return a reference to the i-th euler angles corresponding
+      to this quaternion rotation.
+      @units radians */
+  double GetEuler(int i) const {
+    ComputeDerived();
+    return mEulerAngles(i);
+  }
+
+  /** Retrieves the Euler angles.
+      @param i the euler angle index.
+      @return a reference to the i-th euler angles corresponding
+      to this quaternion rotation.
+      @units degrees */
+  double GetEulerDeg(int i) const {
+    ComputeDerived();
+    return radtodeg*mEulerAngles(i);
+  }
+
+  /** Retrieves sine of the given euler angle.
+      @return the sine of the Euler angle theta (pitch attitude) corresponding
+      to this quaternion rotation.  */
+  double GetSinEuler(int i) const {
+    ComputeDerived();
+    return mEulerSines(i);
+  }
+
+  /** Retrieves cosine of the given euler angle.
+      @return the sine of the Euler angle theta (pitch attitude) corresponding
+      to this quaternion rotation.  */
+  double GetCosEuler(int i) const {
+    ComputeDerived();
+    return mEulerCosines(i);
+  }
+
+  /** 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;
+  }
+
+  /** Inverse of the quaternion.
+
+      Compute and return the inverse of the quaternion so that the orientation
+      represented with *this multiplied with the returned value is equal to
+      the identity orientation.
+  */
+  FGQuaternion Inverse(void) const {
+    double norm = Magnitude();
+    if (norm == 0.0)
+      return *this;
+    double rNorm = 1.0/norm;
+    return FGQuaternion( Entry(1)*rNorm, -Entry(2)*rNorm,
+                         -Entry(3)*rNorm, -Entry(4)*rNorm );
+  }
+
+  /** Conjugate of the quaternion.
+
+      Compute and return the conjugate of the quaternion. This one is equal
+      to the inverse iff the quaternion is normalized.
+  */
+  FGQuaternion Conjugate(void) const {
+    return FGQuaternion( Entry(1), -Entry(2), -Entry(3), -Entry(4) );
+  }
+
+  friend FGQuaternion operator*(double, const FGQuaternion&);
+
+  /** Length of the vector.
+
+      Compute and return the euclidean norm of this vector.
+  */
+  double Magnitude(void) 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(void) 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(void);
+
+  /** 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 the real worker routine
+      \ref FGQuaternion::ComputeDerivedUnconditional(void) const
+      is called.
+      This function is inlined to avoid function calls in the fast path. */
+  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
diff --git a/src/FDM/JSBSim/math/FGRealValue.cpp b/src/FDM/JSBSim/math/FGRealValue.cpp
new file mode 100755 (executable)
index 0000000..d1f97cd
--- /dev/null
@@ -0,0 +1,34 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Module: FGRealValue.cpp
+Author: Jon Berndt
+Date started: 12/10/2004
+Purpose: Stores real values
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGRealValue.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_REALVALUE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGRealValue::FGRealValue(double value) : Value(value)
+{
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGRealValue::GetValue(void) const
+{
+  return Value;
+}
+
+}
diff --git a/src/FDM/JSBSim/math/FGRealValue.h b/src/FDM/JSBSim/math/FGRealValue.h
new file mode 100755 (executable)
index 0000000..334bf84
--- /dev/null
@@ -0,0 +1,59 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Header: FGRealValue.h
+Author: Jon Berndt
+Date started: December 10 2004
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGREALVALUE_H
+#define FGREALVALUE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGParameter.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_REALVALUE "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+  /** Represents a real value
+      @author Jon Berndt
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DECLARATION: FGRealValue
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGRealValue : public FGParameter
+{
+public:
+
+  FGRealValue(double val);
+  ~FGRealValue() {};
+
+  double GetValue(void) const;
+
+private:
+  double Value;
+};
+
+} // namespace JSBSim
+
+#endif
diff --git a/src/FDM/JSBSim/math/FGTable.cpp b/src/FDM/JSBSim/math/FGTable.cpp
new file mode 100644 (file)
index 0000000..b5d6019
--- /dev/null
@@ -0,0 +1,591 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGTable.cpp
+ Author:       Jon S. Berndt
+ Date started: 1/9/2001
+ Purpose:      Models a lookup table
+
+ ------------- Copyright (C) 2001  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
+--------------------------------------------------------------------------------
+Models a lookup table
+
+HISTORY
+--------------------------------------------------------------------------------
+JSB  1/9/00          Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGTable.h"
+
+#if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
+# include <iomanip.h>
+#else
+# include <iomanip>
+#endif
+
+using namespace std;
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_TABLE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGTable::FGTable(int NRows) : nRows(NRows), nCols(1), PropertyManager(0)
+{
+  Type = tt1D;
+  colCounter = 0;
+  rowCounter = 1;
+  nTables = 0;
+
+  Data = Allocate();
+  Debug(0);
+  lastRowIndex=lastColumnIndex=2;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTable::FGTable(const FGTable& t) : PropertyManager(t.PropertyManager)
+{
+  Type = t.Type;
+  colCounter = t.colCounter;
+  rowCounter = t.rowCounter;
+  tableCounter = t.tableCounter;
+  nRows = t.nRows;
+  nCols = t.nCols;
+  nTables = t.nTables;
+  dimension = t.dimension;
+  internal = t.internal;
+
+  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;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(propMan)
+{
+  int i;
+
+  stringstream buf;
+  string property_string;
+  string lookup_axis;
+  string call_type;
+  string parent_type;
+  FGPropertyManager* node;
+  Element *tableData;
+  Element *parent_element;
+  Element *axisElement;
+  string operation_types = "function, product, sum, difference, quotient,"
+                           "pow, abs, sin, cos, asin, acos, tan, atan, table";
+
+  nTables = 0;
+
+  // Is this an internal lookup table?
+
+  internal = false;
+  call_type = el->GetAttributeValue("type");
+  if (call_type == string("internal")) {
+    parent_element = el->GetParent();
+    parent_type = parent_element->GetName();
+    if (operation_types.find(parent_type) == string::npos) {
+      internal = true;
+    } else {
+      // internal table is a child element of a restricted type
+      cerr << endl << fgred << "  An internal table cannot be nested within another type," << endl;
+      cerr << "  such as a function. The 'internal' keyword is ignored." << fgdef << endl << endl;
+    }
+  } else if (!call_type.empty()) {
+    cerr << endl << fgred << "  An unknown table type attribute is listed: " << call_type
+                 << ". Execution cannot continue." << fgdef << endl << endl;
+    abort();
+  }
+
+  // Determine and store the lookup properties for this table unless this table
+  // is part of a 3D table, in which case its independentVar property indexes will
+  // be set by a call from the owning table during creation
+
+  dimension = 0;
+
+  axisElement = el->FindElement("independentVar");
+  if (axisElement) {
+
+    // The 'internal' attribute of the table element cannot be specified
+    // at the same time that independentVars are specified.
+    if (internal) {
+      cerr << endl << fgred << "  This table specifies both 'internal' call type" << endl;
+      cerr << "  and specific lookup properties via the 'independentVar' element." << endl;
+      cerr << "  These are mutually exclusive specifications. The 'internal'" << endl;
+      cerr << "  attribute will be ignored." << fgdef << endl << endl;
+      internal = false;
+    }
+
+    for (i=0; i<3; i++) lookupProperty[i] = 0;
+
+    while (axisElement) {
+      property_string = axisElement->GetDataLine();
+      node = PropertyManager->GetNode(property_string);
+
+      lookup_axis = axisElement->GetAttributeValue("lookup");
+      if (lookup_axis == string("row")) {
+        lookupProperty[eRow] = node;
+      } else if (lookup_axis == string("column")) {
+        lookupProperty[eColumn] = node;
+      } else if (lookup_axis == string("table")) {
+        lookupProperty[eTable] = node;
+      } else { // assumed single dimension table; row lookup
+        lookupProperty[eRow] = node;
+      }
+      dimension++;
+      axisElement = el->FindNextElement("independentVar");
+    }
+
+  } else if (internal) { // This table is an internal table
+
+  // determine how many rows, columns, and tables in this table (dimension).
+
+    if (el->GetNumElements("tableData") > 1) {
+      dimension = 3; // this is a 3D table
+    } else {
+      tableData = el->FindElement("tableData");
+      string test_line = tableData->GetDataLine(1);  // examine second line in table for dimension
+      if (FindNumColumns(test_line) == 2) dimension = 1;    // 1D table
+      else if (FindNumColumns(test_line) > 2) dimension = 2; // 2D table
+      else {
+        cerr << "Invalid number of columns in table" << endl;
+      }
+    }
+
+  } else { // no independentVars found, and table is not marked as internal
+    cerr << endl << fgred << "No independent variable found for table." << fgdef << endl << endl;
+    abort();
+  }
+  // end lookup property code
+
+  tableData = el->FindElement("tableData");
+  for (int i=0; i<tableData->GetNumDataLines(); i++) {
+    buf << tableData->GetDataLine(i) << string(" ");
+  }
+  switch (dimension) {
+  case 1:
+    nRows = tableData->GetNumDataLines();
+    nCols = 1;
+    Type = tt1D;
+    colCounter = 0;
+    rowCounter = 1;
+    Data = Allocate();
+    Debug(0);
+    lastRowIndex = lastColumnIndex = 2;
+    *this << buf;
+    break;
+  case 2:
+    nRows = tableData->GetNumDataLines()-1;
+
+    if (nRows >= 2) nCols = FindNumColumns(tableData->GetDataLine(0));
+    else {
+      cerr << endl << fgred << "Not enough rows in this table." << fgdef << endl;
+      abort();
+    }
+
+    Type = tt2D;
+    colCounter = 1;
+    rowCounter = 0;
+
+    Data = Allocate();
+    lastRowIndex = lastColumnIndex = 2;
+    *this << buf;
+    break;
+  case 3:
+    nTables = el->GetNumElements("tableData");
+    nRows = nTables;
+    nCols = 1;
+    Type = tt3D;
+    colCounter = 1;
+    rowCounter = 1;
+
+    Data = Allocate(); // this data array will contain the keys for the associated tables
+    Tables.reserve(nTables); // necessary?
+    tableData = el->FindElement("tableData");
+    for (i=0; i<nTables; i++) {
+      Tables.push_back(new FGTable(PropertyManager, tableData));
+      Data[i+1][1] = tableData->GetAttributeValueAsNumber("breakPoint");
+      Tables[i]->SetRowIndexProperty(lookupProperty[eRow]);
+      Tables[i]->SetColumnIndexProperty(lookupProperty[eColumn]);
+      tableData = el->FindNextElement("tableData");
+    }
+
+    Debug(0);
+    break;
+  default:
+    cout << "No dimension given" << endl;
+    break;
+  }
+  if (debug_lvl & 1) Print();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double** FGTable::Allocate(void)
+{
+  Data = new double*[nRows+1];
+  for (int r=0; r<=nRows; r++) {
+    Data[r] = new double[nCols+1];
+    for (int c=0; c<=nCols; c++) {
+      Data[r][c] = 0.0;
+    }
+  }
+  return Data;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTable::~FGTable()
+{
+  if (nTables > 0) {
+cout << "nTables = " << nTables << endl;
+    for (int i=0; i<nTables; i++) delete Tables[i];
+    Tables.clear();
+  }
+  for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r];
+  if (Data) delete[] Data;
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+int FGTable::FindNumColumns(string test_line)
+{
+  // determine number of data columns in table (first column is row lookup - don't count)
+  int position=0;
+  int nCols=0;
+  while ((position = test_line.find_first_not_of(" \t", position)) != string::npos) {
+    nCols++;
+    position = test_line.find_first_of(" \t", position);
+  }
+  return nCols;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTable::GetValue(void) const
+{
+  double temp = 0;
+  double temp2 = 0;
+
+  switch (Type) {
+  case tt1D:
+    temp = lookupProperty[eRow]->getDoubleValue();
+    temp2 = GetValue(temp);
+    return temp2;
+  case tt2D:
+    return GetValue(lookupProperty[eRow]->getDoubleValue(),
+                    lookupProperty[eColumn]->getDoubleValue());
+  case tt3D:
+    return GetValue(lookupProperty[eRow]->getDoubleValue(),
+                    lookupProperty[eColumn]->getDoubleValue(),
+                    lookupProperty[eTable]->getDoubleValue());
+  default:
+    cerr << "Attempted to GetValue() for invalid/unknown table type" << endl;
+    throw(string("Attempted to GetValue() for invalid/unknown table type"));
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTable::GetValue(double key) const
+{
+  double Factor, Value, Span;
+  int r=lastRowIndex;
+
+  //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;
+    //cout << "Key underneath table: " << key << endl;
+    return Data[1][1];
+  } else if ( key >= Data[nRows][0] ) {
+    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;
+  // 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;
+    if (Factor > 1.0) Factor = 1.0;
+  } else {
+    Factor = 1.0;
+  }
+
+  Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1];
+
+  return Value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTable::GetValue(double rowKey, double colKey) const
+{
+  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 ) {
+    while ( r <= nRows && Data[r][0] <= rowKey ) { r++; }
+    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;
+  }
+
+  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]);
+
+  if (rFactor > 1.0) rFactor = 1.0;
+  else if (rFactor < 0.0) rFactor = 0.0;
+
+  if (cFactor > 1.0) cFactor = 1.0;
+  else if (cFactor < 0.0) cFactor = 0.0;
+
+  col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1];
+  col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c];
+
+  Value = col1temp + cFactor*(col2temp - col1temp);
+
+  return Value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTable::GetValue(double rowKey, double colKey, double tableKey) const
+{
+  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-2]->GetValue(rowKey, colKey);
+
+  return Value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTable::operator<<(stringstream& in_stream)
+{
+  int startRow=0;
+  int startCol=0;
+
+  if (Type == tt1D || Type == tt3D) startRow = 1;
+  if (Type == tt3D) startCol = 1;
+
+  for (int r=startRow; r<=nRows; r++) {
+    for (int c=startCol; c<=nCols; c++) {
+      if (r != 0 || c != 0) {
+        in_stream >> Data[r][c];
+      }
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTable& FGTable::operator<<(const double n)
+{
+  Data[rowCounter][colCounter] = n;
+  if (colCounter == nCols) {
+    colCounter = 0;
+    rowCounter++;
+  } else {
+    colCounter++;
+  }
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTable& FGTable::operator<<(const int n)
+{
+  *this << (double)n;
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTable::Print(void)
+{
+  int startRow=0;
+  int startCol=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);
+#else
+  ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream
+#endif
+
+  switch(Type) {
+    case tt1D:
+      cout << "    1 dimensional table with " << nRows << " rows." << endl;
+      break;
+    case tt2D:
+      cout << "    2 dimensional table with " << nRows << " rows, " << nCols << " columns." << endl;
+      break;
+    case tt3D:
+      cout << "    3 dimensional table with " << nRows << " rows, "
+                                          << nCols << " columns "
+                                          << nTables << " tables." << endl;
+      break;
+  }
+  cout.precision(4);
+  for (int r=startRow; r<=nRows; r++) {
+    cout << "  ";
+    for (int c=startCol; c<=nCols; c++) {
+      if (r == 0 && c == 0) {
+        cout << "      ";
+      } else {
+        cout << Data[r][c] << "        ";
+        if (Type == tt3D) {
+          cout << endl;
+          Tables[r-1]->Print();
+        }
+      }
+    }
+    cout << endl;
+  }
+  cout.setf(flags); // reset
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGTable::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: FGTable" << endl;
+    if (from == 1) cout << "Destroyed:    FGTable" << 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/math/FGTable.h b/src/FDM/JSBSim/math/FGTable.h
new file mode 100644 (file)
index 0000000..be6e3b8
--- /dev/null
@@ -0,0 +1,276 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGTable.h
+ Author:       Jon S. Berndt
+ Date started: 1/9/2001
+
+ ------------- Copyright (C) 2001  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
+--------------------------------------------------------------------------------
+JSB  1/9/00          Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGTABLE_H
+#define FGTABLE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <input_output/FGXMLElement.h>
+#include "FGParameter.h"
+#include <input_output/FGPropertyManager.h>
+#include <sstream>
+#include <vector>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_TABLE "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+using std::vector;
+using std::stringstream;
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Lookup table class.
+    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
+    @see FGPropeller
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGTable : public FGParameter
+{
+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 table
+  FGTable (FGPropertyManager* propMan, Element* el);
+  FGTable (int );
+  double GetValue(void) const;
+  double GetValue(double key) const;
+  double GetValue(double rowKey, double colKey) const;
+  double GetValue(double rowKey, double colKey, double TableKey) const;
+  /** 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
+      the first row.  The implication of this layout is that there should
+      be no value in the upper left corner of the matrix e.g:
+      <pre>
+           0  10  20 30 ...
+      -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<<(stringstream&);
+  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 SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;}
+  void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;}
+
+  void Print(void);
+
+private:
+  enum type {tt1D, tt2D, tt3D} Type;
+  enum axis {eRow=0, eColumn, eTable};
+  bool internal;
+  FGPropertyManager *lookupProperty[3];
+  double** Data;
+  vector <FGTable*> Tables;
+  int  FindNumColumns(string);
+  int nRows, nCols, nTables, dimension;
+  int colCounter, rowCounter, tableCounter;
+  mutable int lastRowIndex, lastColumnIndex, lastTableIndex;
+  double** Allocate(void);
+  FGPropertyManager* const PropertyManager;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif
+
diff --git a/src/FDM/JSBSim/math/Makefile.am b/src/FDM/JSBSim/math/Makefile.am
new file mode 100644 (file)
index 0000000..107e29f
--- /dev/null
@@ -0,0 +1,9 @@
+noinst_LIBRARIES = libMath.a
+
+libMath_a_SOURCES = FGColumnVector3.cpp FGFunction.cpp FGLocation.cpp FGMatrix33.cpp \
+                    FGPropertyValue.cpp FGQuaternion.cpp FGRealValue.cpp FGTable.cpp
+
+noinst_HEADERS = FGColumnVector3.h FGFunction.h FGLocation.h FGMatrix33.h \
+                 FGParameter.h FGPropertyValue.h FGQuaternion.h FGRealValue.h FGTable.h 
+
+INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp
new file mode 100644 (file)
index 0000000..63f0075
--- /dev/null
@@ -0,0 +1,403 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGAerodynamics.cpp
+ Author:       Jon S. Berndt
+ Date started: 09/13/00
+ Purpose:      Encapsulates the aerodynamic forces
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+09/13/00   JSB   Created
+04/22/01   JSB   Moved code into here from FGAircraft
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGAerodynamics.h"
+#include "FGPropagate.h"
+#include "FGAircraft.h"
+#include "FGState.h"
+#include "FGMassBalance.h"
+#include <input_output/FGPropertyManager.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_AERODYNAMICS;
+
+const unsigned NAxes=6;
+const char* AxisNames[] = { "drag", "side-force", "lift", "rolling-moment",
+                            "pitching-moment","yawing-moment" };
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
+{
+  Name = "FGAerodynamics";
+
+  AxisIdx["DRAG"]  = 0;
+  AxisIdx["SIDE"]  = 1;
+  AxisIdx["LIFT"]  = 2;
+  AxisIdx["ROLL"]  = 3;
+  AxisIdx["PITCH"] = 4;
+  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;
+  bi2vel = ci2vel = 0.0;
+  bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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;
+
+  for (i=0; i<variables.size(); i++)
+    delete variables[i];
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAerodynamics::Run(void)
+{
+  unsigned int axis_ctr, ctr, i;
+  double alpha, twovel;
+
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false; // if paused don't execute
+
+  // calculate some oft-used quantities for speed
+
+  twovel = 2*Auxiliary->GetVt();
+  if (twovel != 0) {
+    bi2vel = Aircraft->GetWingSpan() / twovel;
+    ci2vel = Aircraft->Getcbar() / twovel;
+  }
+  alphaw = Auxiliary->Getalpha() + Aircraft->GetWingIncidence();
+  alpha = Auxiliary->Getalpha();
+  qbar_area = Aircraft->GetWingArea() * Auxiliary->Getqbar();
+
+  if (alphaclmax != 0) {
+    if (alpha > 0.85*alphaclmax) {
+      impending_stall = 10*(alpha/alphaclmax - 0.85);
+    } else {
+      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();
+
+  // Tell the variable functions to cache their values, so while the aerodynamic
+  // functions are being calculated for each axis, these functions do not get
+  // calculated each time, but instead use the values that have already
+  // been calculated for this frame.
+  for (i=0; i<variables.size(); i++) variables[i]->cacheValue(true);
+
+  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
+    for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) {
+      vFs(axis_ctr+1) += Coeff[axis_ctr][ctr]->GetValue();
+    }
+  }
+
+  // calculate lift coefficient squared
+  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;
+
+  // transform stability axis forces into body axes
+  vForces = State->GetTs2b()*vFs;
+
+  vDXYZcg = MassBalance->StructuralToBody(Aircraft->GetXYZrp());
+
+  vMoments = vDXYZcg*vForces; // M = r X F
+
+  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
+    for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) {
+      vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->GetValue();
+    }
+  }
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAerodynamics::Load(Element *element)
+{
+  string parameter, axis, scratch;
+  Element *temp_element, *axis_element, *function_element;
+
+  Debug(2);
+
+  if (temp_element = element->FindElement("alphalimits")) {
+    alphaclmin = temp_element->FindElementValueAsNumberConvertTo("min", "DEG");
+    alphaclmax = temp_element->FindElementValueAsNumberConvertTo("max", "DEG");
+  }
+
+  if (temp_element = element->FindElement("hysteresis_limits")) {
+    alphahystmin = temp_element->FindElementValueAsNumberConvertTo("min", "DEG");
+    alphahystmax = temp_element->FindElementValueAsNumberConvertTo("max", "DEG");
+  }
+
+  function_element = element->FindElement("function");
+  while (function_element) {
+    variables.push_back( new FGFunction(PropertyManager, function_element) );
+    function_element = element->FindNextElement("function");
+  }
+
+  axis_element = element->FindElement("axis");
+  while (axis_element) {
+    CoeffArray ca;
+    axis = axis_element->GetAttributeValue("name");
+    function_element = axis_element->FindElement("function");
+    while (function_element) {
+      ca.push_back( new FGFunction(PropertyManager, function_element) );
+      function_element = axis_element->FindNextElement("function");
+    }
+    Coeff[AxisIdx[axis]] = ca;
+    axis_element = element->FindNextElement("axis");
+  }
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGAerodynamics::GetCoefficientStrings(string delimeter)
+{
+  string CoeffStrings = "";
+  bool firstime = true;
+  unsigned int axis, sd;
+
+  for (sd = 0; sd < variables.size(); sd++) {
+    if (firstime) {
+      firstime = false;
+    } else {
+      CoeffStrings += delimeter;
+    }
+    CoeffStrings += variables[sd]->GetName();
+  }
+
+  for (axis = 0; axis < 6; axis++) {
+    for (sd = 0; sd < Coeff[axis].size(); sd++) {
+      CoeffStrings += delimeter;
+      CoeffStrings += Coeff[axis][sd]->GetName();
+    }
+  }
+  return CoeffStrings;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGAerodynamics::GetCoefficientValues(string delimeter)
+{
+  string SDValues = "";
+  bool firstime = true;
+  unsigned int sd;
+
+  for (sd = 0; sd < variables.size(); sd++) {
+    if (firstime) {
+      firstime = false;
+    } else {
+      SDValues += delimeter;
+    }
+    SDValues += variables[sd]->GetValueAsString();
+  }
+
+  for (unsigned int axis = 0; axis < 6; axis++) {
+    for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
+      SDValues += delimeter;
+      SDValues += Coeff[axis][sd]->GetValueAsString();
+    }
+  }
+
+  return SDValues;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAerodynamics::bind(void)
+{
+  typedef double (FGAerodynamics::*PMF)(int) const;
+
+  PropertyManager->Tie("forces/fbx-aero-lbs", this,1,
+                       (PMF)&FGAerodynamics::GetForces);
+  PropertyManager->Tie("forces/fby-aero-lbs", this,2,
+                       (PMF)&FGAerodynamics::GetForces);
+  PropertyManager->Tie("forces/fbz-aero-lbs", this,3,
+                       (PMF)&FGAerodynamics::GetForces);
+  PropertyManager->Tie("moments/l-aero-lbsft", this,1,
+                       (PMF)&FGAerodynamics::GetMoments);
+  PropertyManager->Tie("moments/m-aero-lbsft", this,2,
+                       (PMF)&FGAerodynamics::GetMoments);
+  PropertyManager->Tie("moments/n-aero-lbsft", this,3,
+                       (PMF)&FGAerodynamics::GetMoments);
+  PropertyManager->Tie("forces/fwx-aero-lbs", this,1,
+                       (PMF)&FGAerodynamics::GetvFs);
+  PropertyManager->Tie("forces/fwy-aero-lbs", this,2,
+                       (PMF)&FGAerodynamics::GetvFs);
+  PropertyManager->Tie("forces/fwz-aero-lbs", this,3,
+                       (PMF)&FGAerodynamics::GetvFs);
+  PropertyManager->Tie("forces/lod-norm", this,
+                       &FGAerodynamics::GetLoD);
+  PropertyManager->Tie("aero/cl-squared", this,
+                       &FGAerodynamics::GetClSquared);
+  PropertyManager->Tie("aero/qbar-area", &qbar_area);
+  PropertyManager->Tie("aero/alpha-max-deg", this,
+                       &FGAerodynamics::GetAlphaCLMax,
+                       &FGAerodynamics::SetAlphaCLMax,
+                       true);
+  PropertyManager->Tie("aero/alpha-min-deg", this,
+                       &FGAerodynamics::GetAlphaCLMin,
+                       &FGAerodynamics::SetAlphaCLMin,
+                       true);
+  PropertyManager->Tie("aero/bi2vel", this,
+                       &FGAerodynamics::GetBI2Vel);
+  PropertyManager->Tie("aero/ci2vel", this,
+                       &FGAerodynamics::GetCI2Vel);
+  PropertyManager->Tie("aero/alpha-wing-rad", this,
+                       &FGAerodynamics::GetAlphaW);
+  PropertyManager->Tie("systems/stall-warn-norm", this,
+                        &FGAerodynamics::GetStallWarn);
+  PropertyManager->Tie("aero/stall-hyst-norm", this,
+                        &FGAerodynamics::GetHysteresisParm);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAerodynamics::unbind(void)
+{
+  unsigned i,j;
+
+  PropertyManager->Untie("forces/fbx-aero-lbs");
+  PropertyManager->Untie("forces/fby-aero-lbs");
+  PropertyManager->Untie("forces/fbz-aero-lbs");
+  PropertyManager->Untie("moments/l-aero-lbsft");
+  PropertyManager->Untie("moments/m-aero-lbsft");
+  PropertyManager->Untie("moments/n-aero-lbsft");
+  PropertyManager->Untie("forces/fwx-aero-lbs");
+  PropertyManager->Untie("forces/fwy-aero-lbs");
+  PropertyManager->Untie("forces/fwz-aero-lbs");
+  PropertyManager->Untie("forces/lod-norm");
+  PropertyManager->Untie("aero/cl-squared");
+  PropertyManager->Untie("aero/qbar-area");
+  PropertyManager->Untie("aero/alpha-max-deg");
+  PropertyManager->Untie("aero/alpha-min-deg");
+  PropertyManager->Untie("aero/bi2vel");
+  PropertyManager->Untie("aero/ci2vel");
+  PropertyManager->Untie("aero/alpha-wing-rad");
+  PropertyManager->Untie("aero/stall-hyst-norm");
+  PropertyManager->Untie("systems/stall-warn-norm");
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGAerodynamics::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 2) { // Loader
+      cout << endl << "  Aerodynamics: " << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGAerodynamics" << endl;
+    if (from == 1) cout << "Destroyed:    FGAerodynamics" << 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;
+    }
+  }
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/models/FGAerodynamics.h b/src/FDM/JSBSim/models/FGAerodynamics.h
new file mode 100644 (file)
index 0000000..39713a0
--- /dev/null
@@ -0,0 +1,196 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGAerodynamics.h
+ Author:       Jon S. Berndt
+ Date started: 09/13/00
+
+ ------------- 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
+--------------------------------------------------------------------------------
+09/13/00   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGAERODYNAMICS_H
+#define FGAERODYNAMICS_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#    include <map>
+#  else
+#    include <vector.h>
+#    include <map.h>
+#  endif
+#else
+#  include <vector>
+#  include <map>
+#endif
+
+#include "FGModel.h"
+#include <math/FGFunction.h>
+#include <math/FGColumnVector3.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_AERODYNAMICS "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates the aerodynamic calculations.
+    This class owns and contains the list of coefficients that define the
+    aerodynamic properties of this aircraft. Here also, such unique phenomena
+    as ground effect and maximum lift curve tailoff are handled.
+    @config
+    <pre>
+    \<AERODYNAMICS>
+       \<AXIS NAME="{LIFT|DRAG|SIDE|ROLL|PITCH|YAW}">
+         {Coefficient definitions}
+       \</AXIS>
+       {Additional axis definitions}
+    \</AERODYNAMICS> </pre>
+
+    @author Jon S. Berndt, Tony Peden
+    $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGAerodynamics : public FGModel {
+
+public:
+  /** Constructor
+      @param Executive a pointer to the parent executive object */
+  FGAerodynamics(FGFDMExec* Executive);
+  /// Destructor
+  ~FGAerodynamics();
+
+  /** Runs the Aerodynamics model; called by the Executive
+      @return false if no error */
+  bool Run(void);
+
+  /** Loads the Aerodynamics model.
+      The Load function for this class expects the XML parser to
+      have found the AERODYNAMICS keyword in the configuration file.
+      @param element pointer to the current XML element for aerodynamics parameters.
+      @return true if successful */
+  bool Load(Element* element);
+
+  /** Gets the total aerodynamic force vector.
+      @return a force vector reference. */
+  FGColumnVector3& GetForces(void) {return vForces;}
+
+  /** Gets the aerodynamic force for an axis.
+      @param n Axis index. This could be 0, 1, or 2, or one of the
+               axis enums: eX, eY, eZ.
+      @return the force acting on an axis */
+  double GetForces(int n) const {return vForces(n);}
+
+  /** Gets the total aerodynamic moment vector.
+      @return a moment vector reference. */
+  FGColumnVector3& GetMoments(void) {return vMoments;}
+
+  /** Gets the aerodynamic moment for an axis.
+      @return the moment about a single axis (as described also in the
+              similar call to GetForces(int n).*/
+  double GetMoments(int n) const {return vMoments(n);}
+
+  FGColumnVector3& GetvLastFs(void) { return vLastFs; }
+  double GetvLastFs(int axis) const { return vLastFs(axis); }
+  FGColumnVector3& GetvFs(void) { return vFs; }
+  double GetvFs(int axis) const { return vFs(axis); }
+  inline double GetLoD(void) const { return lod; }
+  inline double GetClSquared(void) const { return clsq; }
+  inline double GetAlphaCLMax(void) const { return alphaclmax; }
+  inline double GetAlphaCLMin(void) const { return alphaclmin; }
+
+  inline double GetAlphaHystMax(void) const { return alphahystmax; }
+  inline double GetAlphaHystMin(void) const { return alphahystmin; }
+  inline double GetHysteresisParm(void) const { return stall_hyst; }
+  inline double GetStallWarn(void) const { return impending_stall; }
+  double GetAlphaW(void) const { return alphaw; }
+
+  double GetBI2Vel(void) const { return bi2vel; }
+  double GetCI2Vel(void) const { return ci2vel; }
+
+  inline void SetAlphaCLMax(double tt) { alphaclmax=tt; }
+  inline void SetAlphaCLMin(double tt) { alphaclmin=tt; }
+
+  /** Gets the strings for the current set of coefficients.
+      @param delimeter either a tab or comma string depending on output type
+      @return a string containing the descriptive names for all coefficients */
+  string GetCoefficientStrings(string delimeter);
+
+  /** Gets the coefficient values.
+      @param delimeter either a tab or comma string depending on output type
+      @return a string containing the numeric values for the current set of
+      coefficients */
+  string GetCoefficientValues(string delimeter);
+
+  void bind(void);
+  void unbind(void);
+
+private:
+  typedef map<string,int> AxisIndex;
+  AxisIndex AxisIdx;
+  vector <FGFunction*> variables;
+  typedef vector <FGFunction*> CoeffArray;
+  CoeffArray* Coeff;
+  FGColumnVector3 vFs;
+  FGColumnVector3 vForces;
+  FGColumnVector3 vMoments;
+  FGColumnVector3 vLastFs;
+  FGColumnVector3 vDXYZcg;
+  double alphaclmax, alphaclmin;
+  double alphahystmax, alphahystmin;
+  double impending_stall, stall_hyst;
+  double bi2vel, ci2vel,alphaw;
+  double clsq, lod, qbar_area;
+
+  typedef double (FGAerodynamics::*PMF)(int) const;
+
+  void Debug(int from);
+};
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGAircraft.cpp b/src/FDM/JSBSim/models/FGAircraft.cpp
new file mode 100644 (file)
index 0000000..fd6f9fc
--- /dev/null
@@ -0,0 +1,324 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGAircraft.cpp
+ Author:       Jon S. Berndt
+ Date started: 12/12/98
+ Purpose:      Encapsulates an aircraft
+ 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
+--------------------------------------------------------------------------------
+Models the aircraft reactions and forces. This class is instantiated by the
+FGFDMExec class and scheduled as an FDM entry.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef FGFS
+#  ifndef __BORLANDC__
+#    include <simgear/compiler.h>
+#  endif
+#  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 "FGAircraft.h"
+#include "FGMassBalance.h"
+#include "FGInertial.h"
+#include "FGGroundReactions.h"
+#include "FGAerodynamics.h"
+#include <FGState.h>
+#include <FGFDMExec.h>
+#include "FGPropagate.h"
+#include <input_output/FGPropertyManager.h>
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+GLOBAL DATA
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_AIRCRAFT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGAircraft";
+  WingSpan = 0.0;
+  HTailArea = VTailArea = 0.0;
+  HTailArm  = VTailArm  = 0.0;
+  lbarh = lbarv = 0.0;
+  vbarh = vbarv = 0.0;
+  WingIncidence = 0.0;
+
+  bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGAircraft::~FGAircraft()
+{
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAircraft::Run(void)
+{
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  vForces.InitMatrix();
+  vForces += Aerodynamics->GetForces();
+  vForces += Propulsion->GetForces();
+  vForces += GroundReactions->GetForces();
+
+  vMoments.InitMatrix();
+  vMoments += Aerodynamics->GetMoments();
+  vMoments += Propulsion->GetMoments();
+  vMoments += GroundReactions->GetMoments();
+
+//  printf("%s:%i\n", __FILE__, __LINE__);
+  vBodyAccel = vForces/MassBalance->GetMass();
+
+//  printf("%s:%i\n", __FILE__, __LINE__);
+  vNcg = vBodyAccel/Inertial->gravity();
+
+  vNwcg = State->GetTb2s() * vNcg;
+  vNwcg(3) = -1*vNwcg(3) + 1;
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGAircraft::GetNlf(void)
+{
+  return -1*Aerodynamics->GetvFs(3)/MassBalance->GetWeight();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAircraft::Load(Element* el)
+{
+  string element_name;
+  Element* element;
+
+  if (el->FindElement("wingarea"))
+    WingArea = el->FindElementValueAsNumberConvertTo("wingarea", "FT2");
+  if (el->FindElement("wingspan"))
+    WingSpan = el->FindElementValueAsNumberConvertTo("wingspan", "FT");
+  if (el->FindElement("chord"))
+    cbar = el->FindElementValueAsNumberConvertTo("chord", "FT");
+  if (el->FindElement("wing_incidence"))
+    WingIncidence = el->FindElementValueAsNumberConvertTo("wing_incidence", "DEG");
+  if (el->FindElement("htailarea"))
+    HTailArea = el->FindElementValueAsNumberConvertTo("htailarea", "FT2");
+  if (el->FindElement("htailarm"))
+    HTailArm = el->FindElementValueAsNumberConvertTo("htailarm", "FT");
+  if (el->FindElement("vtailarea"))
+    VTailArea = el->FindElementValueAsNumberConvertTo("vtailarea", "FT2");
+  if (el->FindElement("vtailarm"))
+    VTailArm = el->FindElementValueAsNumberConvertTo("vtailarm", "FT");
+
+  // Find all LOCATION elements that descend from this METRICS branch of the
+  // config file. This would be CG location, eyepoint, etc.
+
+  element = el->FindElement("location");
+  while (element) {
+    element_name = element->GetAttributeValue("name");
+
+    if (element_name == "AERORP") vXYZrp = element->FindElementTripletConvertTo("IN");
+    else if (element_name == "EYEPOINT") vXYZep = element->FindElementTripletConvertTo("IN");
+    else if (element_name == "VRP") vXYZvrp = element->FindElementTripletConvertTo("IN");
+
+    element = el->FindNextElement("location");
+  }
+
+  // calculate some derived parameters
+  if (cbar != 0.0) {
+    lbarh = HTailArm/cbar;
+    lbarv = VTailArm/cbar;
+    if (WingArea != 0.0) {
+      vbarh = HTailArm*HTailArea / (cbar*WingArea);
+      vbarv = VTailArm*VTailArea / (cbar*WingArea);
+    }
+  }
+
+  Debug(2);
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAircraft::bind(void)
+{
+  typedef double (FGAircraft::*PMF)(int) const;
+  PropertyManager->Tie("metrics/Sw-sqft", this, &FGAircraft::GetWingArea);
+  PropertyManager->Tie("metrics/bw-ft", this, &FGAircraft::GetWingSpan);
+  PropertyManager->Tie("metrics/cbarw-ft", this, &FGAircraft::Getcbar);
+  PropertyManager->Tie("metrics/iw-deg", this, &FGAircraft::GetWingIncidence);
+  PropertyManager->Tie("metrics/Sh-sqft", this, &FGAircraft::GetHTailArea);
+  PropertyManager->Tie("metrics/lh-ft", this, &FGAircraft::GetHTailArm);
+  PropertyManager->Tie("metrics/Sv-sqft", this, &FGAircraft::GetVTailArea);
+  PropertyManager->Tie("metrics/lv-ft", this, &FGAircraft::GetVTailArm);
+  PropertyManager->Tie("metrics/lh-norm", this, &FGAircraft::Getlbarh);
+  PropertyManager->Tie("metrics/lv-norm", this, &FGAircraft::Getlbarv);
+  PropertyManager->Tie("metrics/vbarh-norm", this, &FGAircraft::Getvbarh);
+  PropertyManager->Tie("metrics/vbarv-norm", this, &FGAircraft::Getvbarv);
+  PropertyManager->Tie("moments/l-total-lbsft", this, eL, (PMF)&FGAircraft::GetMoments);
+  PropertyManager->Tie("moments/m-total-lbsft", this, eM, (PMF)&FGAircraft::GetMoments);
+  PropertyManager->Tie("moments/n-total-lbsft", this, eN, (PMF)&FGAircraft::GetMoments);
+  PropertyManager->Tie("forces/fbx-total-lbs", this, eX, (PMF)&FGAircraft::GetForces);
+  PropertyManager->Tie("forces/fby-total-lbs", this, eY, (PMF)&FGAircraft::GetForces);
+  PropertyManager->Tie("forces/fbz-total-lbs", this, eZ, (PMF)&FGAircraft::GetForces);
+  PropertyManager->Tie("metrics/aero-rp-x-in", this, eX, (PMF)&FGAircraft::GetXYZrp);
+  PropertyManager->Tie("metrics/aero-rp-y-in", this, eY, (PMF)&FGAircraft::GetXYZrp);
+  PropertyManager->Tie("metrics/aero-rp-z-in", this, eZ, (PMF)&FGAircraft::GetXYZrp);
+  PropertyManager->Tie("metrics/eyepoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZep);
+  PropertyManager->Tie("metrics/eyepoint-y-in", this, eY,(PMF)&FGAircraft::GetXYZep);
+  PropertyManager->Tie("metrics/eyepoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZep);
+  PropertyManager->Tie("metrics/visualrefpoint-x-in", this, eX, (PMF)&FGAircraft::GetXYZvrp);
+  PropertyManager->Tie("metrics/visualrefpoint-y-in", this, eY, (PMF)&FGAircraft::GetXYZvrp);
+  PropertyManager->Tie("metrics/visualrefpoint-z-in", this, eZ, (PMF)&FGAircraft::GetXYZvrp);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAircraft::unbind(void)
+{
+  PropertyManager->Untie("metrics/Sw-sqft");
+  PropertyManager->Untie("metrics/bw-ft");
+  PropertyManager->Untie("metrics/cbarw-ft");
+  PropertyManager->Untie("metrics/iw-deg");
+  PropertyManager->Untie("metrics/Sh-sqft");
+  PropertyManager->Untie("metrics/lh-ft");
+  PropertyManager->Untie("metrics/Sv-sqft");
+  PropertyManager->Untie("metrics/lv-ft");
+  PropertyManager->Untie("metrics/lh-norm");
+  PropertyManager->Untie("metrics/lv-norm");
+  PropertyManager->Untie("metrics/vbarh-norm");
+  PropertyManager->Untie("metrics/vbarv-norm");
+  PropertyManager->Untie("moments/l-total-lbsft");
+  PropertyManager->Untie("moments/m-total-lbsft");
+  PropertyManager->Untie("moments/n-total-lbsft");
+  PropertyManager->Untie("forces/fbx-total-lbs");
+  PropertyManager->Untie("forces/fby-total-lbs");
+  PropertyManager->Untie("forces/fbz-total-lbs");
+  PropertyManager->Untie("metrics/aero-rp-x-in");
+  PropertyManager->Untie("metrics/aero-rp-y-in");
+  PropertyManager->Untie("metrics/aero-rp-z-in");
+  PropertyManager->Untie("metrics/eyepoint-x-in");
+  PropertyManager->Untie("metrics/eyepoint-y-in");
+  PropertyManager->Untie("metrics/eyepoint-z-in");
+  PropertyManager->Untie("metrics/visualrefpoint-x-in");
+  PropertyManager->Untie("metrics/visualrefpoint-y-in");
+  PropertyManager->Untie("metrics/visualrefpoint-z-in");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGAircraft::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 2) { // Loading
+      cout << endl << "  Aircraft Metrics:" << endl;
+      cout << "    WingArea: " << WingArea  << endl;
+      cout << "    WingSpan: " << WingSpan  << endl;
+      cout << "    Incidence: " << WingIncidence << endl;
+      cout << "    Chord: " << cbar << endl;
+      cout << "    H. Tail Area: " << HTailArea << endl;
+      cout << "    H. Tail Arm: " << HTailArm << endl;
+      cout << "    V. Tail Area: " << VTailArea << endl;
+      cout << "    V. Tail Arm: " << VTailArm << endl;
+      cout << "    Eyepoint (x, y, z): " << vXYZep << endl;
+      cout << "    Ref Pt (x, y, z): " << vXYZrp << endl;
+      cout << "    Visual Ref Pt (x, y, z): " << vXYZvrp << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGAircraft" << endl;
+    if (from == 1) cout << "Destroyed:    FGAircraft" << 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;
+    }
+  }
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/models/FGAircraft.h b/src/FDM/JSBSim/models/FGAircraft.h
new file mode 100644 (file)
index 0000000..29d555d
--- /dev/null
@@ -0,0 +1,184 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGAircraft.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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGAIRCRAFT_H
+#define FGAIRCRAFT_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#    include <iterator>
+#  else
+#    include <vector.h>
+#    include <iterator.h>
+#  endif
+#else
+#  include <vector>
+#  include <iterator>
+#endif
+
+#include "FGModel.h"
+#include <input_output/FGXMLElement.h>
+#include <math/FGColumnVector3.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_AIRCRAFT "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates an Aircraft and its systems.
+    Owns all the parts (other classes) which make up this aircraft. This includes
+    the Engines, Tanks, Propellers, Nozzles, Aerodynamic and Mass properties,
+    landing gear, etc. These constituent parts may actually run as separate
+    JSBSim models themselves, but the responsibility for initializing them and
+    for retrieving their force and moment contributions falls to FGAircraft.
+    @author Jon S. Berndt
+    @version $Id$
+    @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 FGAircraft : public FGModel {
+public:
+  /** Constructor
+      @param Executive a pointer to the parent executive object */
+  FGAircraft(FGFDMExec *Executive);
+  
+  /// Destructor
+  ~FGAircraft();
+
+  /** Runs the Aircraft model; called by the Executive
+      @see JSBSim.cpp documentation
+      @return false if no error */
+  bool Run(void);
+  
+  /** Loads the aircraft.
+      The executive calls this method to load the aircraft into JSBSim.
+      @param el a pointer to the element tree
+      @return true if successful */
+  bool Load(Element* el);
+  
+  /** Gets the aircraft name
+      @return the name of the aircraft as a string type */
+  inline string GetAircraftName(void) { return AircraftName; }
+  
+  /// Gets the wing area
+  double GetWingArea(void) const { return WingArea; }
+  /// Gets the wing span
+  double GetWingSpan(void) const { return WingSpan; }
+  /// Gets the average wing chord
+  double Getcbar(void) const { return cbar; }
+  inline double GetWingIncidence(void) const { return WingIncidence; }
+  inline double GetHTailArea(void) const { return HTailArea; }
+  inline double GetHTailArm(void)  const { return HTailArm; }
+  inline double GetVTailArea(void) const { return VTailArea; }
+  inline double GetVTailArm(void)  const { return VTailArm; }
+  inline double Getlbarh(void) const { return lbarh; } // HTailArm / cbar
+  inline double Getlbarv(void) const { return lbarv; } // VTailArm / cbar
+  inline double Getvbarh(void) const { return vbarh; } // H. Tail Volume
+  inline double Getvbarv(void) const { return vbarv; } // V. Tail Volume
+  inline FGColumnVector3& GetMoments(void) { return vMoments; }
+  inline double GetMoments(int idx) const { return vMoments(idx); }
+  inline FGColumnVector3& GetForces(void) { return vForces; }
+  inline double GetForces(int idx) const { return vForces(idx); }
+  inline FGColumnVector3& GetBodyAccel(void) { return vBodyAccel; }
+  inline double GetBodyAccel(int idx) { return vBodyAccel(idx); }
+  inline FGColumnVector3& GetNcg   (void)  { return vNcg; }
+  inline double GetNcg(int idx)  { return vNcg(idx); }
+  inline FGColumnVector3& GetXYZrp(void) { return vXYZrp; }
+  inline FGColumnVector3& GetXYZvrp(void) { return vXYZvrp; }
+  inline FGColumnVector3& GetXYZep(void) { return vXYZep; }
+  inline double GetXYZrp(int idx) const { return vXYZrp(idx); }
+  inline double GetXYZvrp(int idx) const { return vXYZvrp(idx); }
+  inline double GetXYZep(int idx) const { return vXYZep(idx); }
+  inline void SetAircraftName(string name) {AircraftName = name;}
+
+  double GetNlf(void);
+
+  inline FGColumnVector3& GetNwcg(void) { return vNwcg; }
+
+  void bind(void);
+  void unbind(void);
+
+private:
+  FGColumnVector3 vMoments;
+  FGColumnVector3 vForces;
+  FGColumnVector3 vXYZrp;
+  FGColumnVector3 vXYZvrp;
+  FGColumnVector3 vXYZep;
+  FGColumnVector3 vDXYZcg;
+  FGColumnVector3 vBodyAccel;
+  FGColumnVector3 vNcg;
+  FGColumnVector3 vNwcg;
+
+  double WingArea, WingSpan, cbar, WingIncidence;
+  double HTailArea, VTailArea, HTailArm, VTailArm;
+  double lbarh,lbarv,vbarh,vbarv;
+  string AircraftName;
+
+  void Debug(int from);
+};
+
+} // namespace JSBSim
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGAtmosphere.cpp b/src/FDM/JSBSim/models/FGAtmosphere.cpp
new file mode 100644 (file)
index 0000000..b7ad766
--- /dev/null
@@ -0,0 +1,582 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGAtmosphere.cpp
+ Author:       Jon Berndt
+               Implementation of 1959 Standard Atmosphere added by Tony Peden
+ Date started: 11/24/98
+ Purpose:      Models the atmosphere
+ 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
+ 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
+--------------------------------------------------------------------------------
+Models the atmosphere. The equation used below was determined by a third order
+curve fit using Excel. The data is from the ICAO atmosphere model.
+
+HISTORY
+--------------------------------------------------------------------------------
+11/24/98   JSB   Created
+07/23/99   TP    Added implementation of 1959 Standard Atmosphere
+                 Moved calculation of Mach number to FGPropagate
+                 Later updated to '76 model
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+[1]   Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
+      1989, ISBN 0-07-001641-0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGAtmosphere.h"
+#include <FGState.h>
+#include <FGFDMExec.h>
+#include "FGAircraft.h"
+#include "FGPropagate.h"
+#include "FGInertial.h"
+#include <input_output/FGPropertyManager.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_ATMOSPHERE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGAtmosphere";
+  lastIndex = 0;
+  h = 0.0;
+  psiw = 0.0;
+  htab[0]=0;
+  htab[1]=36089.239;
+  htab[2]=65616.798;
+  htab[3]=104986.878;
+  htab[4]=154199.475;
+  htab[5]=170603.675;
+  htab[6]=200131.234;
+  htab[7]=259186.352; //ft.
+
+  MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
+//   turbType = ttNone;
+  turbType = ttStandard;
+//   turbType = ttBerndt;
+  TurbGain = 0.0;
+  TurbRate = 1.0;
+
+  T_dev_sl = T_dev = delta_T = 0.0;
+  StandardTempOnly = false;
+
+  bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGAtmosphere::~FGAtmosphere()
+{
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAtmosphere::InitModel(void)
+{
+  FGModel::InitModel();
+
+  UseInternal();  // this is the default
+
+  Calculate(h);
+  StdSLtemperature = SLtemperature = 518.67;
+  StdSLpressure    = SLpressure = 2116.22;
+  StdSLdensity     = SLdensity = 0.00237767;
+  StdSLsoundspeed  = SLsoundspeed = sqrt(SHRatio*Reng*StdSLtemperature);
+  rSLtemperature = 1.0/StdSLtemperature;
+  rSLpressure    = 1.0/StdSLpressure;
+  rSLdensity     = 1.0/StdSLdensity;
+  rSLsoundspeed  = 1.0/StdSLsoundspeed;
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAtmosphere::Run(void)
+{
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  T_dev = 0.0;
+  h = Propagate->Geth();
+
+  if (!useExternal) {
+    Calculate(h);
+    CalculateDerived();
+  } else {
+    CalculateDerived();
+  } 
+
+  Debug(2);
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// See reference 1
+
+void FGAtmosphere::Calculate(double altitude)
+{
+  double slope, reftemp, refpress;
+  int i = 0;
+
+  i = lastIndex;
+  if (altitude < htab[lastIndex]) {
+    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;
+      altitude = htab[7];
+    } else {
+      i = lastIndex+1;
+      while (htab[i+1] < altitude) i++;
+    }
+  }
+
+  switch(i) {
+  case 1:     // 36089 ft.
+    slope     = 0;
+    reftemp   = 389.97;
+    refpress  = 472.452;
+    //refdens   = 0.000706032;
+    break;
+  case 2:     // 65616 ft.
+    slope     = 0.00054864;
+    reftemp   = 389.97;
+    refpress  = 114.636;
+    //refdens   = 0.000171306;
+    break;
+  case 3:     // 104986 ft.
+    slope     = 0.00153619;
+    reftemp   = 411.57;
+    refpress  = 8.36364;
+    //refdens   = 1.18422e-05;
+    break;
+  case 4:     // 154199 ft.
+    slope     = 0;
+    reftemp   = 487.17;
+    refpress  = 0.334882;
+    //refdens   = 4.00585e-7;
+    break;
+  case 5:     // 170603 ft.
+    slope     = -0.00109728;
+    reftemp   = 487.17;
+    refpress  = 0.683084;
+    //refdens   = 8.17102e-7;
+    break;
+  case 6:     // 200131 ft.
+    slope     = -0.00219456;
+    reftemp   = 454.17;
+    refpress  = 0.00684986;
+    //refdens   = 8.77702e-9;
+    break;
+  case 7:     // 259186 ft.
+    slope     = 0;
+    reftemp   = 325.17;
+    refpress  = 0.000122276;
+    //refdens   = 2.19541e-10;
+    break;
+  case 0:
+  default:     // sea level
+    slope     = -0.00356616; // R/ft.
+    reftemp   = 518.67;    // R
+    refpress  = 2116.22;    // psf
+    //refdens   = 0.00237767;  // slugs/cubic ft.
+    break;
+
+  }
+
+  // If delta_T is set, then that is our temperature deviation at any altitude.
+  // If not, then we'll estimate a deviation based on the sea level deviation (if set).
+
+  if(!StandardTempOnly) { 
+    T_dev = 0.0; 
+    if (delta_T != 0.0) {
+      T_dev = delta_T;
+    } else {
+      if ((altitude < 36089.239) && (T_dev_sl != 0.0)) {
+        T_dev = T_dev_sl * ( 1.0 - (altitude/36089.239));
+      }
+    }
+    reftemp+=T_dev;
+  } 
+
+  if (slope == 0) {
+    intTemperature = reftemp;
+    intPressure = refpress*exp(-Inertial->SLgravity()/(reftemp*Reng)*(altitude-htab[i]));
+    intDensity = intPressure/(Reng*intTemperature);
+  } else {
+    intTemperature = reftemp+slope*(altitude-htab[i]);
+    intPressure = refpress*pow(intTemperature/reftemp,-Inertial->SLgravity()/(slope*Reng));
+    intDensity = intPressure/(Reng*intTemperature);
+  }
+
+  lastIndex=i;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Calculate parameters derived from T, P and rho
+
+void FGAtmosphere::CalculateDerived(void)
+{
+  T_dev = (*temperature) - GetTemperature(h);
+  density_altitude = h + T_dev * 66.7;
+
+  if (turbType != ttStandard) {
+    Turbulence();
+    vWindNED += vTurbulence;
+  }
+  if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) );
+  if (psiw < 0) psiw += 2*M_PI;
+
+  soundspeed = sqrt(SHRatio*Reng*(*temperature));
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Get the standard atmospheric properties at a specified altitude
+
+void FGAtmosphere::GetStdAtmosphere(double altitude) {
+  StandardTempOnly = true;
+  Calculate(altitude);
+  StandardTempOnly = false;
+  atmosphere.Temperature = intTemperature;
+  atmosphere.Pressure = intPressure;
+  atmosphere.Density = intDensity;
+
+  // Reset the internal atmospheric state
+  Calculate(h);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Get the standard pressure at a specified altitude
+
+double FGAtmosphere::GetPressure(double altitude) {
+  GetStdAtmosphere(altitude);
+  return atmosphere.Pressure;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Get the standard temperature at a specified altitude
+
+double FGAtmosphere::GetTemperature(double altitude) {
+  GetStdAtmosphere(altitude);
+  return atmosphere.Temperature;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Get the standard density at a specified altitude
+
+double FGAtmosphere::GetDensity(double altitude) {
+  GetStdAtmosphere(altitude);
+  return atmosphere.Density;
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// square a value, but preserve the original sign
+
+static inline double square_signed (double value)
+{
+    if (value < 0)
+        return value * value * -1;
+    else
+        return value * value;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAtmosphere::Turbulence(void)
+{
+  switch (turbType) {
+  case ttStandard: {
+    vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
+    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;
+                                // Scale the magnitude so that it moves
+                                // away from the peaks
+    MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
+                         (1 + fabs(Magnitude)));
+    MagnitudeAccel    += MagnitudedAccelDt*rate*TurbRate*State->Getdt();
+    Magnitude         += MagnitudeAccel*rate*State->Getdt();
+
+    vDirectiondAccelDt.Normalize();
+
+                                // deemphasise non-vertical forces
+    vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX));
+    vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY));
+
+    vDirectionAccel += vDirectiondAccelDt*rate*TurbRate*State->Getdt();
+    vDirectionAccel.Normalize();
+    vDirection      += vDirectionAccel*rate*State->Getdt();
+
+    vDirection.Normalize();
+
+                                // Diminish turbulence within three wingspans
+                                // of the ground
+    vTurbulence = TurbGain * Magnitude * vDirection;
+    double HOverBMAC = Auxiliary->GetHOverBMAC();
+    if (HOverBMAC < 3.0)
+        vTurbulence *= (HOverBMAC / 3.0) * (HOverBMAC / 3.0);
+
+    vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
+
+    vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
+
+    if (Aircraft->GetWingSpan() > 0) {
+      vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
+    } else {
+      vTurbPQR(eP) = vBodyTurbGrad(eY)/30.0;
+    }
+//     if (Aircraft->GetHTailArm() != 0.0)
+//       vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
+//     else
+//       vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
+
+    if (Aircraft->GetVTailArm() > 0)
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
+    else
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
+
+                                // Clear the horizontal forces
+                                // actually felt by the plane, now
+                                // that we've used them to calculate
+                                // moments.
+    vTurbulence(eX) = 0.0;
+    vTurbulence(eY) = 0.0;
+
+    break;
+  }
+  case ttBerndt: {
+    vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
+    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();
+
+    vDirectiondAccelDt.Normalize();
+    vDirectionAccel += vDirectiondAccelDt*rate*State->Getdt();
+    vDirectionAccel.Normalize();
+    vDirection      += vDirectionAccel*rate*State->Getdt();
+
+                                // Diminish z-vector within two wingspans
+                                // of the ground
+    double HOverBMAC = Auxiliary->GetHOverBMAC();
+    if (HOverBMAC < 2.0)
+        vDirection(eZ) *= HOverBMAC / 2.0;
+
+    vDirection.Normalize();
+
+    vTurbulence = TurbGain*Magnitude * vDirection;
+    vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
+
+    vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
+    vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
+    if (Aircraft->GetHTailArm() > 0)
+      vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
+    else
+      vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
+
+    if (Aircraft->GetVTailArm() > 0)
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
+    else
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
+
+    break;
+  }
+  default:
+    break;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAtmosphere::UseExternal(void)
+{
+  temperature=&exTemperature;
+  pressure=&exPressure;
+  density=&exDensity;
+  useExternal=true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAtmosphere::UseInternal(void)
+{
+  temperature=&intTemperature;
+  pressure=&intPressure;
+  density=&intDensity;
+  useExternal=false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAtmosphere::bind(void)
+{
+  typedef double (FGAtmosphere::*PMF)(int) const;
+  PropertyManager->Tie("atmosphere/T-R", this,
+                       &FGAtmosphere::GetTemperature);
+  PropertyManager->Tie("atmosphere/rho-slugs_ft3", this,
+                       &FGAtmosphere::GetDensity);
+//  PropertyManager->Tie("atmosphere/P-psf", this,
+//                       &FGAtmosphere::GetPressure);
+  PropertyManager->Tie("atmosphere/a-fps", this,
+                       &FGAtmosphere::GetSoundSpeed);
+  PropertyManager->Tie("atmosphere/T-sl-R", this,
+                       &FGAtmosphere::GetTemperatureSL);
+  PropertyManager->Tie("atmosphere/rho-sl-slugs_ft3", this,
+                       &FGAtmosphere::GetDensitySL);
+  PropertyManager->Tie("atmosphere/P-sl-psf", this,
+                       &FGAtmosphere::GetPressureSL);
+  PropertyManager->Tie("atmosphere/a-sl-fps", this,
+                       &FGAtmosphere::GetSoundSpeedSL);
+  PropertyManager->Tie("atmosphere/theta", this,
+                       &FGAtmosphere::GetTemperatureRatio);
+  PropertyManager->Tie("atmosphere/sigma", this,
+                       &FGAtmosphere::GetDensityRatio);
+  PropertyManager->Tie("atmosphere/delta", this,
+                       &FGAtmosphere::GetPressureRatio);
+  PropertyManager->Tie("atmosphere/a-ratio", this,
+                       &FGAtmosphere::GetSoundSpeedRatio);
+  PropertyManager->Tie("atmosphere/psiw-rad", this,
+                       &FGAtmosphere::GetWindPsi);
+  PropertyManager->Tie("atmosphere/delta-T", this,
+                       &FGAtmosphere::GetDeltaT, &FGAtmosphere::SetDeltaT);
+  PropertyManager->Tie("atmosphere/T-sl-dev-F", this,
+                       &FGAtmosphere::GetSLTempDev, &FGAtmosphere::SetSLTempDev);
+  PropertyManager->Tie("atmosphere/density-altitude", this,
+                       &FGAtmosphere::GetDensityAltitude);
+  PropertyManager->Tie("atmosphere/p-turb-rad_sec", this,1,
+                       (PMF)&FGAtmosphere::GetTurbPQR);
+  PropertyManager->Tie("atmosphere/q-turb-rad_sec", this,2,
+                       (PMF)&FGAtmosphere::GetTurbPQR);
+  PropertyManager->Tie("atmosphere/r-turb-rad_sec", this,3,
+                       (PMF)&FGAtmosphere::GetTurbPQR);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAtmosphere::unbind(void)
+{
+  PropertyManager->Untie("atmosphere/T-R");
+  PropertyManager->Untie("atmosphere/rho-slugs_ft3");
+//  PropertyManager->Untie("atmosphere/P-psf");
+  PropertyManager->Untie("atmosphere/a-fps");
+  PropertyManager->Untie("atmosphere/T-sl-R");
+  PropertyManager->Untie("atmosphere/rho-sl-slugs_ft3");
+  PropertyManager->Untie("atmosphere/P-sl-psf");
+  PropertyManager->Untie("atmosphere/a-sl-fps");
+  PropertyManager->Untie("atmosphere/delta-T");
+  PropertyManager->Untie("atmosphere/T-sl-dev-F");
+  PropertyManager->Untie("atmosphere/density-altitude");
+  PropertyManager->Untie("atmosphere/theta");
+  PropertyManager->Untie("atmosphere/sigma");
+  PropertyManager->Untie("atmosphere/delta");
+  PropertyManager->Untie("atmosphere/a-ratio");
+  PropertyManager->Untie("atmosphere/psiw-rad");
+  PropertyManager->Untie("atmosphere/p-turb-rad_sec");
+  PropertyManager->Untie("atmosphere/q-turb-rad_sec");
+  PropertyManager->Untie("atmosphere/r-turb-rad_sec");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGAtmosphere::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: FGAtmosphere" << endl;
+    if (from == 1) cout << "Destroyed:    FGAtmosphere" << 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 & 128) { // Turbulence
+    if (frame == 0 && from == 2) {
+      cout << "vTurbulence(X), vTurbulence(Y), vTurbulence(Z), "
+           << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), "
+           << "vDirection(X), vDirection(Y), vDirection(Z), "
+           << "Magnitude, "
+           << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl;
+    } else if (from == 2) {
+      cout << vTurbulence << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl;
+    }
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/models/FGAtmosphere.h b/src/FDM/JSBSim/models/FGAtmosphere.h
new file mode 100644 (file)
index 0000000..fd0500a
--- /dev/null
@@ -0,0 +1,217 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGAtmosphere.h
+ Author:       Jon Berndt
+               Implementation of 1959 Standard Atmosphere added by Tony Peden
+ Date started: 11/24/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
+--------------------------------------------------------------------------------
+11/24/98   JSB   Created
+07/23/99   TP    Added implementation of 1959 Standard Atmosphere
+                 Moved calculation of Mach number to FGPropagate
+                 Updated to '76 model
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGAtmosphere_H
+#define FGAtmosphere_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGModel.h"
+#include <math/FGColumnVector3.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_ATMOSPHERE "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models the standard atmosphere.
+    @author Tony Peden, Jon Berndt
+    @version $Id$
+    @see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
+         1989, ISBN 0-07-001641-0
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGAtmosphere : public FGModel {
+public:
+
+  /// Constructor
+  FGAtmosphere(FGFDMExec*);
+  /// Destructor
+  ~FGAtmosphere();
+  /** Runs the Atmosphere model; called by the Executive
+      @return false if no error */
+  bool Run(void);
+  bool InitModel(void);
+
+  /// Returns the temperature in degrees Rankine.
+  inline double GetTemperature(void) const {return *temperature;}
+  /** Returns the density in slugs/ft^3.
+      <i>This function may <b>only</b> be used if Run() is called first.</i> */
+  inline double GetDensity(void)  const {return *density;}
+  /// Returns the pressure in psf.
+  inline double GetPressure(void)  const {return *pressure;}
+  /// Returns the standard pressure at a specified altitude
+  double GetPressure(double altitude);
+  /// Returns the standard temperature at a specified altitude
+  double GetTemperature(double altitude);
+  /// Returns the standard density at a specified altitude
+  double GetDensity(double altitude);
+  /// Returns the speed of sound in ft/sec.
+  inline double GetSoundSpeed(void) const {return soundspeed;}
+
+  /// Returns the sea level temperature in degrees Rankine.
+  inline double GetTemperatureSL(void) const { return SLtemperature; }
+  /// Returns the sea level density in slugs/ft^3
+  inline double GetDensitySL(void)  const { return SLdensity; }
+  /// Returns the sea level pressure in psf.
+  inline double GetPressureSL(void) const { return SLpressure; }
+  /// Returns the sea level speed of sound in ft/sec.
+  inline double GetSoundSpeedSL(void) const { return SLsoundspeed; }
+
+  /// Returns the ratio of at-altitude temperature over the sea level value.
+  inline double GetTemperatureRatio(void) const { return (*temperature)*rSLtemperature; }
+  /// Returns the ratio of at-altitude density over the sea level value.
+  inline double GetDensityRatio(void) const { return (*density)*rSLdensity; }
+  /// Returns the ratio of at-altitude pressure over the sea level value.
+  inline double GetPressureRatio(void) const { return (*pressure)*rSLpressure; }
+  /// Returns the ratio of at-altitude sound speed over the sea level value.
+  inline double GetSoundSpeedRatio(void) const { return soundspeed*rSLsoundspeed; }
+
+  /// Tells the simulator to use an externally calculated atmosphere model.
+  void UseExternal(void);
+  /// Tells the simulator to use the internal atmosphere model.
+  void UseInternal(void);  //this is the default
+  /// Gets the boolean that tells if the external atmosphere model is being used.
+  bool External(void) { return useExternal; }
+
+  /// Provides the external atmosphere model with an interface to set the temperature.
+  inline void SetExTemperature(double t)  { exTemperature=t; }
+  /// Provides the external atmosphere model with an interface to set the density.
+  inline void SetExDensity(double d)      { exDensity=d; }
+  /// Provides the external atmosphere model with an interface to set the pressure.
+  inline void SetExPressure(double p)     { exPressure=p; }
+
+  /// Sets the temperature deviation at sea-level in degrees Fahrenheit
+  inline void SetSLTempDev(double d)  { T_dev_sl = d; }
+  /// Gets the temperature deviation at sea-level in degrees Fahrenheit
+  inline double GetSLTempDev(void) const { return T_dev_sl; }
+  /// Sets the current delta-T in degrees Fahrenheit
+  inline void SetDeltaT(double d)  { delta_T = d; } 
+  /// Gets the current delta-T in degrees Fahrenheit
+  inline double GetDeltaT(void) const  { return delta_T; } 
+  /// Gets the at-altitude temperature deviation in degrees Fahrenheit
+  inline double GetTempDev(void) const { return T_dev; }
+  /// Gets the density altitude in feet
+  inline double GetDensityAltitude(void) const { return density_altitude; }
+
+  /// Sets the wind components in NED frame.
+  inline void SetWindNED(double wN, double wE, double wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;}
+
+  /// Retrieves the wind components in NED frame.
+  inline FGColumnVector3& GetWindNED(void) { return vWindNED; }
+  
+  /** Retrieves the wind direction. The direction is defined as north=0 and
+      increases counterclockwise. The wind heading is returned in radians.*/
+  inline double GetWindPsi(void) const { return psiw; }
+  
+  inline void SetTurbGain(double tt) {TurbGain = tt;}
+  inline void SetTurbRate(double tt) {TurbRate = tt;}
+  
+  inline double GetTurbPQR(int idx) const {return vTurbPQR(idx);}
+  inline FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;}
+  
+  void bind(void);
+  void unbind(void);
+
+  
+protected:
+  double rho;
+
+  enum tType {ttStandard, ttBerndt, ttNone} turbType;
+  struct atmType {double Temperature; double Pressure; double Density;};
+
+  int lastIndex;
+  double h;
+  double htab[8];
+  double StdSLtemperature,StdSLdensity,StdSLpressure,StdSLsoundspeed;
+  double rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
+  double SLtemperature,SLdensity,SLpressure,SLsoundspeed;
+  double *temperature,*density,*pressure;
+  double soundspeed;
+  bool useExternal;
+  double exTemperature,exDensity,exPressure;
+  double intTemperature, intDensity, intPressure;
+  double T_dev_sl, T_dev, delta_T, density_altitude;
+  atmType atmosphere;
+  bool StandardTempOnly;
+
+  double MagnitudedAccelDt, MagnitudeAccel, Magnitude;
+  double TurbGain;
+  double TurbRate;
+  FGColumnVector3 vDirectiondAccelDt;
+  FGColumnVector3 vDirectionAccel;
+  FGColumnVector3 vDirection;
+  FGColumnVector3 vTurbulence;
+  FGColumnVector3 vTurbulenceGrad;
+  FGColumnVector3 vBodyTurbGrad;
+  FGColumnVector3 vTurbPQR;
+
+  FGColumnVector3 vWindNED;
+  double psiw;
+
+  /// Calculate the atmosphere for the given altitude, including effects of temperature deviation.
+  void Calculate(double altitude);
+  /// Calculate atmospheric properties other than the basic T, P and rho.
+  void CalculateDerived(void);
+  /// Get T, P and rho for a standard atmosphere at the given altitude.
+  void GetStdAtmosphere(double altitude);
+  void Turbulence(void);
+  void Debug(int from);
+};
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGAuxiliary.cpp b/src/FDM/JSBSim/models/FGAuxiliary.cpp
new file mode 100755 (executable)
index 0000000..056c1c0
--- /dev/null
@@ -0,0 +1,428 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+ 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 calculates various auxiliary parameters.
+
+REFERENCES
+  Anderson, John D. "Introduction to Flight", 3rd Edition, McGraw-Hill, 1989
+                    pgs. 112-126
+HISTORY
+--------------------------------------------------------------------------------
+01/26/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGAuxiliary.h"
+#include "FGAerodynamics.h"
+#include "FGPropagate.h"
+#include "FGAtmosphere.h"
+#include <FGState.h>
+#include <FGFDMExec.h>
+#include "FGAircraft.h"
+#include "FGInertial.h"
+#include <input_output/FGPropertyManager.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_AUXILIARY;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGAuxiliary";
+  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);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGAuxiliary::~FGAuxiliary()
+{
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAuxiliary::Run()
+{
+  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()) return true;
+  if (FDMExec->Holding()) return false;
+
+  p = Atmosphere->GetPressure();
+  rhosl = Atmosphere->GetDensitySL();
+  psl = Atmosphere->GetPressureSL();
+  sat = Atmosphere->GetTemperature();
+
+// Rotation
+
+  double cTht = Propagate->GetCosEuler(eTht);
+  double cPhi = Propagate->GetCosEuler(ePhi);
+  double sPhi = Propagate->GetSinEuler(ePhi);
+
+  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;
+  }
+
+// 12/16/2005, JSB: For ground handling purposes, at this time, let's ramp
+// in the effects of wind from 10 fps to 30 fps when there is weight on the
+// landing gear wheels.
+
+  if (GroundReactions->GetWOW() && vUVW(eU) < 10) {
+    vAeroPQR = vPQR;
+    vAeroUVW = vUVW;
+  } else if (GroundReactions->GetWOW() && vUVW(eU) < 30) {
+    double factor = (vUVW(eU) - 10.0)/20.0;
+    vAeroPQR = vPQR + factor*Atmosphere->GetTurbPQR();
+    vAeroUVW = vUVW + factor*Propagate->GetTl2b()*Atmosphere->GetWindNED();
+  } else {
+    vAeroPQR = vPQR + Atmosphere->GetTurbPQR();
+    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 {
+    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;
+
+  if (Vt != 0) {
+    hdot_Vt = -vVel(eDown)/Vt;
+    if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);
+  } else {
+    gamma = 0.0;
+  }
+
+  tat = sat*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow
+  tatc = RankineToCelsius(tat);
+
+  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) {
+    vcas = sqrt(7*psl/rhosl*(A-1));
+    veas = sqrt(2*qbar/rhosl);
+  } else {
+    vcas = veas = 0.0;
+  }
+
+  vPilotAccel.InitMatrix();
+  if ( Vt > 1.0 ) {
+     vPilotAccel =  Aerodynamics->GetForces()
+                    +  Propulsion->GetForces()
+                    +  GroundReactions->GetForces();
+     vPilotAccel /= MassBalance->GetMass();
+     vToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep());
+     vPilotAccel += Propagate->GetPQRdot() * vToEyePt;
+     vPilotAccel += vPQR * (vPQR * vToEyePt);
+  } else {
+     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;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGAuxiliary::GetHeadWind(void)
+{
+  double psiw,vw;
+
+  psiw = Atmosphere->GetWindPsi();
+  vw = Atmosphere->GetWindNED().Magnitude();
+
+  return vw*cos(psiw - Propagate->GetEuler(ePsi));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGAuxiliary::GetCrossWind(void)
+{
+  double psiw,vw;
+
+  psiw = Atmosphere->GetWindPsi();
+  vw = Atmosphere->GetWindNED().Magnitude();
+
+  return  vw*sin(psiw - Propagate->GetEuler(ePsi));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAuxiliary::bind(void)
+{
+  typedef double (FGAuxiliary::*PMF)(int) const;
+  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", 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);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGAuxiliary::unbind(void)
+{
+  PropertyManager->Untie("velocities/vc-fps");
+  PropertyManager->Untie("velocities/vc-kts");
+  PropertyManager->Untie("velocities/ve-fps");
+  PropertyManager->Untie("velocities/ve-kts");
+  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");
+  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");
+  PropertyManager->Untie("accelerations/n-pilot-x-norm");
+  PropertyManager->Untie("accelerations/n-pilot-y-norm");
+  PropertyManager->Untie("accelerations/n-pilot-z-norm");
+  PropertyManager->Untie("position/epa-rad");
+  /* PropertyManager->Untie("atmosphere/headwind-fps");
+  PropertyManager->Untie("atmosphere/crosswind-fps"); */
+  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");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGAuxiliary::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: FGAuxiliary" << endl;
+    if (from == 1) cout << "Destroyed:    FGAuxiliary" << 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 (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
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/models/FGAuxiliary.h b/src/FDM/JSBSim/models/FGAuxiliary.h
new file mode 100644 (file)
index 0000000..297b3a0
--- /dev/null
@@ -0,0 +1,245 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGAUXILIARY_H
+#define FGAUXILIARY_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGModel.h"
+#include <math/FGColumnVector3.h>
+#include <math/FGLocation.h>
+#include "FGPropagate.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_AUXILIARY "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGAuxiliary : public FGModel {
+public:
+  /** Constructor
+      @param Executive a pointer to the parent executive object */
+  FGAuxiliary(FGFDMExec* Executive);
+
+  /// Destructor
+  ~FGAuxiliary();
+
+  /** Runs the Auxiliary routines; called by the Executive
+      @return false if no error */
+  bool Run(void);
+
+// 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
+  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, 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 Debug(int from);
+};
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp
new file mode 100644 (file)
index 0000000..0c106ce
--- /dev/null
@@ -0,0 +1,844 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGFCS.cpp
+ Author:       Jon Berndt
+ Date started: 12/12/98
+ Purpose:      Model the flight controls
+ 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 models the flight controls for a specific airplane
+
+HISTORY
+--------------------------------------------------------------------------------
+12/12/98   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCS.h"
+#include <FGFDMExec.h>
+#include <input_output/FGPropertyManager.h>
+#include <fstream>
+
+#include <models/flight_control/FGFilter.h>
+#include <models/flight_control/FGDeadBand.h>
+#include <models/flight_control/FGGain.h>
+#include <models/flight_control/FGGradient.h>
+#include <models/flight_control/FGSwitch.h>
+#include <models/flight_control/FGSummer.h>
+#include <models/flight_control/FGKinemat.h>
+#include <models/flight_control/FGFCSFunction.h>
+#include <models/flight_control/FGSensor.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FCS;
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#define snprintf _snprintf
+#endif
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGFCS::FGFCS(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  int i;
+  Name = "FGFCS";
+
+  DaCmd = DeCmd = DrCmd = DsCmd = DfCmd = DsbCmd = DspCmd = 0;
+  PTrimCmd = YTrimCmd = RTrimCmd = 0.0;
+  GearCmd = GearPos = 1; // default to gear down
+  LeftBrake = RightBrake = CenterBrake = 0.0;
+
+  bind();
+  for (i=0;i<=NForms;i++) {
+    DePos[i] = DaLPos[i] = DaRPos[i] = DrPos[i] = 0.0;
+    DfPos[i] = DsbPos[i] = DspPos[i] = 0.0;
+  }
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGFCS::~FGFCS()
+{
+  if (PropertyManager->HasNode("fcs")) unbind( PropertyManager->GetNode("fcs") );
+  if (PropertyManager->HasNode("ap")) unbind( PropertyManager->GetNode("ap") );
+  PropertyManager->Untie( "gear/gear-cmd-norm" );
+  PropertyManager->Untie( "gear/gear-pos-norm" );
+
+  ThrottleCmd.clear();
+  ThrottlePos.clear();
+  MixtureCmd.clear();
+  MixturePos.clear();
+  PropAdvanceCmd.clear();
+  PropAdvance.clear();
+  SteerPosDeg.clear();
+  PropFeatherCmd.clear();
+  PropFeather.clear();
+
+  unsigned int i;
+
+  for (i=0;i<APComponents.size();i++) delete APComponents[i];
+  for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i];
+  for (i=0;i<sensors.size();i++) delete sensors[i];
+
+  APComponents.clear();
+  FCSComponents.clear();
+  sensors.clear();
+  interface_properties.clear();
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Notes: In this logic the default engine commands are set. This is simply a
+// sort of safe-mode method in case the user has not defined control laws for
+// throttle, mixture, and prop-advance. The throttle, mixture, and prop advance
+// positions are set equal to the respective commands. Any control logic that is
+// actually present in the flight_control or autopilot section will override
+// these simple assignments.
+
+bool FGFCS::Run(void)
+{
+  unsigned int i;
+
+  if (FGModel::Run()) return true; // fast exit if nothing to do
+  if (FDMExec->Holding()) return false;
+
+  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<PropFeather.size(); i++) PropFeather[i] = PropFeatherCmd[i];
+
+
+  // Set the default steering angle
+  for (i=0; i<SteerPosDeg.size(); i++) {
+    FGLGear* gear = GroundReactions->GetGearUnit(i);
+    SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() );
+  }
+
+  // Cycle through the sensor, autopilot, and flight control components
+  for (i=0; i<sensors.size(); i++) sensors[i]->Run();
+  for (i=0; i<APComponents.size(); i++) APComponents[i]->Run();
+  for (i=0; i<FCSComponents.size(); i++) FCSComponents[i]->Run();
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetDaLPos( int form , double pos )
+{
+  switch(form) {
+  case ofRad:
+    DaLPos[ofRad] = pos;
+    DaLPos[ofDeg] = pos*radtodeg;
+    break;
+  case ofDeg:
+    DaLPos[ofRad] = pos*degtorad;
+    DaLPos[ofDeg] = pos;
+    break;
+  case ofNorm:
+    DaLPos[ofNorm] = pos;
+  }
+  DaLPos[ofMag] = fabs(DaLPos[ofRad]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetDaRPos( int form , double pos )
+{
+  switch(form) {
+  case ofRad:
+    DaRPos[ofRad] = pos;
+    DaRPos[ofDeg] = pos*radtodeg;
+    break;
+  case ofDeg:
+    DaRPos[ofRad] = pos*degtorad;
+    DaRPos[ofDeg] = pos;
+    break;
+  case ofNorm:
+    DaRPos[ofNorm] = pos;
+  }
+  DaRPos[ofMag] = fabs(DaRPos[ofRad]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetDePos( int form , double pos )
+{
+  switch(form) {
+  case ofRad:
+    DePos[ofRad] = pos;
+    DePos[ofDeg] = pos*radtodeg;
+    break;
+  case ofDeg:
+    DePos[ofRad] = pos*degtorad;
+    DePos[ofDeg] = pos;
+    break;
+  case ofNorm:
+    DePos[ofNorm] = pos;
+  }
+  DePos[ofMag] = fabs(DePos[ofRad]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetDrPos( int form , double pos )
+{
+  switch(form) {
+  case ofRad:
+    DrPos[ofRad] = pos;
+    DrPos[ofDeg] = pos*radtodeg;
+    break;
+  case ofDeg:
+    DrPos[ofRad] = pos*degtorad;
+    DrPos[ofDeg] = pos;
+    break;
+  case ofNorm:
+    DrPos[ofNorm] = pos;
+  }
+  DrPos[ofMag] = fabs(DrPos[ofRad]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetDfPos( int form , double pos )
+{
+  switch(form) {
+  case ofRad:
+    DfPos[ofRad] = pos;
+    DfPos[ofDeg] = pos*radtodeg;
+    break;
+  case ofDeg:
+    DfPos[ofRad] = pos*degtorad;
+    DfPos[ofDeg] = pos;
+    break;
+  case ofNorm:
+    DfPos[ofNorm] = pos;
+  }
+  DfPos[ofMag] = fabs(DfPos[ofRad]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetDsbPos( int form , double pos )
+{
+  switch(form) {
+  case ofRad:
+    DsbPos[ofRad] = pos;
+    DsbPos[ofDeg] = pos*radtodeg;
+    break;
+  case ofDeg:
+    DsbPos[ofRad] = pos*degtorad;
+    DsbPos[ofDeg] = pos;
+    break;
+  case ofNorm:
+    DsbPos[ofNorm] = pos;
+  }
+  DsbPos[ofMag] = fabs(DsbPos[ofRad]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetDspPos( int form , double pos )
+{
+  switch(form) {
+  case ofRad:
+    DspPos[ofRad] = pos;
+    DspPos[ofDeg] = pos*radtodeg;
+    break;
+  case ofDeg:
+    DspPos[ofRad] = pos*degtorad;
+    DspPos[ofDeg] = pos;
+    break;
+  case ofNorm:
+    DspPos[ofNorm] = pos;
+  }
+  DspPos[ofMag] = fabs(DspPos[ofRad]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetThrottleCmd(int engineNum, double setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<ThrottleCmd.size();ctr++) ThrottleCmd[ctr] = setting;
+    } else {
+      ThrottleCmd[engineNum] = setting;
+    }
+  } else {
+    cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
+         << " engines exist, but attempted throttle command is for engine "
+         << engineNum << endl;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetThrottlePos(int engineNum, double setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<ThrottlePos.size();ctr++) ThrottlePos[ctr] = setting;
+    } else {
+      ThrottlePos[engineNum] = setting;
+    }
+  } else {
+    cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
+         << " engines exist, but attempted throttle position setting is for engine "
+         << engineNum << endl;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGFCS::GetThrottleCmd(int engineNum) const
+{
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+       cerr << "Cannot get throttle value for ALL engines" << endl;
+    } else {
+      return ThrottleCmd[engineNum];
+    }
+  } else {
+    cerr << "Throttle " << engineNum << " does not exist! " << ThrottleCmd.size()
+         << " engines exist, but throttle setting for engine " << engineNum
+         << " is selected" << endl;
+  }
+  return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGFCS::GetThrottlePos(int engineNum) const
+{
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+       cerr << "Cannot get throttle value for ALL engines" << endl;
+    } else {
+      return ThrottlePos[engineNum];
+    }
+  } else {
+    cerr << "Throttle " << engineNum << " does not exist! " << ThrottlePos.size()
+         << " engines exist, but attempted throttle position setting is for engine "
+         << engineNum << endl;
+  }
+  return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetMixtureCmd(int engineNum, double setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<MixtureCmd.size();ctr++) MixtureCmd[ctr] = setting;
+    } else {
+      MixtureCmd[engineNum] = setting;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetMixturePos(int engineNum, double setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<=MixtureCmd.size();ctr++) MixturePos[ctr] = MixtureCmd[ctr];
+    } else {
+      MixturePos[engineNum] = setting;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetPropAdvanceCmd(int engineNum, double setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<PropAdvanceCmd.size();ctr++) PropAdvanceCmd[ctr] = setting;
+    } else {
+      PropAdvanceCmd[engineNum] = setting;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetPropAdvance(int engineNum, double setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<=PropAdvanceCmd.size();ctr++) PropAdvance[ctr] = PropAdvanceCmd[ctr];
+    } else {
+      PropAdvance[engineNum] = setting;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetFeatherCmd(int engineNum, bool setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<PropFeatherCmd.size();ctr++) PropFeatherCmd[ctr] = setting;
+    } else {
+      PropFeatherCmd[engineNum] = setting;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::SetPropFeather(int engineNum, bool setting)
+{
+  unsigned int ctr;
+
+  if (engineNum < (int)ThrottlePos.size()) {
+    if (engineNum < 0) {
+      for (ctr=0;ctr<=PropFeatherCmd.size();ctr++) PropFeather[ctr] = PropFeatherCmd[ctr];
+    } else {
+      PropFeather[engineNum] = setting;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGFCS::Load(Element* el)
+{
+  string name, file, fname, comp_name, interface_property_string;
+  unsigned i;
+  vector <FGFCSComponent*> *Components;
+  Element *FCS_cfg, *document, *component_element, *property_element, *sensor_element;
+  Element *channel_element;
+  ifstream* controls_file = new ifstream();
+  FGXMLParse controls_file_parser;
+
+  Components=0;
+  // Determine if the FCS/Autopilot is defined inline in the aircraft configuration
+  // file or in a separate file. Set up the Element pointer as appropriate.
+
+  string separator = "/";
+#ifdef macintosh
+  separator = ";";
+#endif
+
+  name = el->GetAttributeValue("name");
+
+  if (name.empty()) {
+    fname = el->GetAttributeValue("file");
+    file = FDMExec->GetAircraftPath() + separator + FDMExec->GetModelName() + separator + fname + ".xml";
+    if (fname.empty()) {
+      cerr << "FCS/Autopilot does not appear to be defined inline nor in a file" << endl;
+      return false;
+    } else {
+      controls_file->open(file.c_str());
+      readXML(*controls_file, controls_file_parser);
+      delete controls_file;
+      document = controls_file_parser.GetDocument();
+    }
+  } else {
+    document = el;
+  }
+
+  if (document->GetName() == "autopilot") {
+    Components = &APComponents;
+    Name = "Autopilot: " + document->GetAttributeValue("name");
+  } else if (document->GetName() == "flight_control") {
+    Components = &FCSComponents;
+    Name = "FCS: " + document->GetAttributeValue("name");
+  }
+
+  Debug(2);
+
+  // ToDo: How do these get untied?
+  // ToDo: Consider having INPUT and OUTPUT interface properties. Would then
+  //       have to duplicate this block of code after channel read code.
+  //       Input properties could be write only (nah), and output could be read
+  //       only.
+
+  if (document->GetName() == "flight_control") bindModel();
+
+  property_element = document->FindElement("property");
+  while (property_element) {
+    interface_properties.push_back(new double(0));
+    interface_property_string = property_element->GetDataLine();
+    PropertyManager->Tie(interface_property_string, interface_properties.back());
+    property_element = document->FindNextElement("property");
+  }
+
+  sensor_element = document->FindElement("sensor");
+  while (sensor_element) {
+    try {
+      sensors.push_back(new FGSensor(this, sensor_element));
+    } catch (string s) {
+      cerr << highint << fgred << endl << "  " << s << endl;
+      return false;
+    }
+    sensor_element = document->FindNextElement("sensor");
+  }
+
+  channel_element = document->FindElement("channel");
+  while (channel_element) {
+    component_element = channel_element->FindElement("component");
+    if (component_element) {
+      cout << "This form of the component specification is being deprecated" << endl;
+    } else {
+      component_element = channel_element->GetElement();
+    }
+    while (component_element) {
+      comp_name = component_element->GetAttributeValue("type");
+      try {
+        if ((comp_name == "LAG_FILTER") ||
+            (comp_name == "LEAD_LAG_FILTER") ||
+            (comp_name == "SECOND_ORDER_FILTER") ||
+            (comp_name == "WASHOUT_FILTER") ||
+            (comp_name == "INTEGRATOR") ||
+            (component_element->GetName() == string("lag_filter")) ||
+            (component_element->GetName() == string("lead_lag_filter")) ||
+            (component_element->GetName() == string("washout_filter")) ||
+            (component_element->GetName() == string("second_order_filter")) ||
+            (component_element->GetName() == string("integrator")) )
+        {
+          Components->push_back(new FGFilter(this, component_element));
+        } else if ((comp_name == "PURE_GAIN") ||
+                   (comp_name == "SCHEDULED_GAIN") ||
+                   (comp_name == "AEROSURFACE_SCALE") ||
+                   (component_element->GetName() == string("pure_gain")) ||
+                   (component_element->GetName() == string("scheduled_gain")) ||
+                   (component_element->GetName() == string("aerosurface_scale")))
+        {
+          Components->push_back(new FGGain(this, component_element));
+        } else if ((comp_name == "SUMMER") || (component_element->GetName() == string("summer"))) {
+          Components->push_back(new FGSummer(this, component_element));
+        } else if ((comp_name == "DEADBAND") || (component_element->GetName() == string("deadband"))) {
+          Components->push_back(new FGDeadBand(this, component_element));
+        } else if (comp_name == "GRADIENT") {
+          Components->push_back(new FGGradient(this, component_element));
+        } else if ((comp_name == "SWITCH") || (component_element->GetName() == string("switch"))) {
+          Components->push_back(new FGSwitch(this, component_element));
+        } else if ((comp_name == "KINEMAT") || (component_element->GetName() == string("kinematic"))) {
+          Components->push_back(new FGKinemat(this, component_element));
+        } else if ((comp_name == "FUNCTION") || (component_element->GetName() == string("fcs_function"))) {
+          Components->push_back(new FGFCSFunction(this, component_element));
+        } else {
+          cerr << "Unknown FCS component: " << comp_name << endl;
+        }
+      } catch(string s) {
+        cerr << highint << fgred << endl << "  " << s << endl;
+        cerr << reset << endl;
+        return false;
+      }
+      if (comp_name.empty()) { // comp_name will be empty if using new format
+        component_element = channel_element->GetNextElement();
+      } else {
+        component_element = channel_element->FindNextElement("component");
+      }
+    }
+    channel_element = document->FindNextElement("channel");
+  }
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGFCS::GetBrake(FGLGear::BrakeGroup bg)
+{
+  switch (bg) {
+  case FGLGear::bgLeft:
+    return LeftBrake;
+  case FGLGear::bgRight:
+    return RightBrake;
+  case FGLGear::bgCenter:
+    return CenterBrake;
+  default:
+    cerr << "GetBrake asked to return a bogus brake value" << endl;
+  }
+  return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGFCS::GetComponentStrings(string delimeter)
+{
+  unsigned int comp;
+  string CompStrings = "";
+  bool firstime = true;
+
+  for (comp = 0; comp < FCSComponents.size(); comp++) {
+    if (firstime) firstime = false;
+    else          CompStrings += delimeter;
+
+    CompStrings += FCSComponents[comp]->GetName();
+  }
+
+  for (comp = 0; comp < APComponents.size(); comp++)
+  {
+    CompStrings += delimeter;
+    CompStrings += APComponents[comp]->GetName();
+  }
+
+  return CompStrings;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGFCS::GetComponentValues(string delimeter)
+{
+  unsigned int comp;
+  string CompValues = "";
+  char buffer[12];
+  bool firstime = true;
+
+  for (comp = 0; comp < FCSComponents.size(); comp++) {
+    if (firstime) firstime = false;
+    else          CompValues += delimeter;
+
+    sprintf(buffer, "%9.6f", FCSComponents[comp]->GetOutput());
+    CompValues += string(buffer);
+  }
+
+  for (comp = 0; comp < APComponents.size(); comp++) {
+    sprintf(buffer, "%s%9.6f", delimeter.c_str(), APComponents[comp]->GetOutput());
+    CompValues += string(buffer);
+  }
+
+  return CompValues;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::AddThrottle(void)
+{
+  ThrottleCmd.push_back(0.0);
+  ThrottlePos.push_back(0.0);
+  MixtureCmd.push_back(0.0);     // assume throttle and mixture are coupled
+  MixturePos.push_back(0.0);
+  PropAdvanceCmd.push_back(0.0); // assume throttle and prop pitch are coupled
+  PropAdvance.push_back(0.0);
+  PropFeatherCmd.push_back(false);
+  PropFeather.push_back(false);
+
+  unsigned int num = ThrottleCmd.size()-1;
+  bindThrottle(num);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::AddGear(void)
+{
+  SteerPosDeg.push_back(0.0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::bind(void)
+{
+  PropertyManager->Tie("fcs/aileron-cmd-norm", this, &FGFCS::GetDaCmd, &FGFCS::SetDaCmd);
+  PropertyManager->Tie("fcs/elevator-cmd-norm", this, &FGFCS::GetDeCmd, &FGFCS::SetDeCmd);
+  PropertyManager->Tie("fcs/rudder-cmd-norm", this, &FGFCS::GetDrCmd, &FGFCS::SetDrCmd);
+  PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGFCS::GetDsCmd, &FGFCS::SetDsCmd);
+  PropertyManager->Tie("fcs/flap-cmd-norm", this, &FGFCS::GetDfCmd, &FGFCS::SetDfCmd);
+  PropertyManager->Tie("fcs/speedbrake-cmd-norm", this, &FGFCS::GetDsbCmd, &FGFCS::SetDsbCmd);
+  PropertyManager->Tie("fcs/spoiler-cmd-norm", this, &FGFCS::GetDspCmd, &FGFCS::SetDspCmd);
+  PropertyManager->Tie("fcs/pitch-trim-cmd-norm", this, &FGFCS::GetPitchTrimCmd, &FGFCS::SetPitchTrimCmd);
+  PropertyManager->Tie("fcs/roll-trim-cmd-norm", this, &FGFCS::GetRollTrimCmd, &FGFCS::SetRollTrimCmd);
+  PropertyManager->Tie("fcs/yaw-trim-cmd-norm", this, &FGFCS::GetYawTrimCmd, &FGFCS::SetYawTrimCmd);
+  PropertyManager->Tie("gear/gear-cmd-norm", this, &FGFCS::GetGearCmd, &FGFCS::SetGearCmd);
+
+  PropertyManager->Tie("fcs/left-aileron-pos-rad", this, ofRad, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
+  PropertyManager->Tie("fcs/left-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
+  PropertyManager->Tie("fcs/left-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaLPos, &FGFCS::SetDaLPos);
+  PropertyManager->Tie("fcs/mag-left-aileron-pos-rad", this, ofMag, &FGFCS::GetDaLPos);
+
+  PropertyManager->Tie("fcs/right-aileron-pos-rad", this, ofRad, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
+  PropertyManager->Tie("fcs/right-aileron-pos-deg", this, ofDeg, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
+  PropertyManager->Tie("fcs/right-aileron-pos-norm", this, ofNorm, &FGFCS::GetDaRPos, &FGFCS::SetDaRPos);
+  PropertyManager->Tie("fcs/mag-right-aileron-pos-rad", this, ofMag, &FGFCS::GetDaRPos);
+
+  PropertyManager->Tie("fcs/elevator-pos-rad", this, ofRad, &FGFCS::GetDePos, &FGFCS::SetDePos);
+  PropertyManager->Tie("fcs/elevator-pos-deg", this, ofDeg, &FGFCS::GetDePos, &FGFCS::SetDePos);
+  PropertyManager->Tie("fcs/elevator-pos-norm", this, ofNorm, &FGFCS::GetDePos, &FGFCS::SetDePos);
+  PropertyManager->Tie("fcs/mag-elevator-pos-rad", this, ofMag, &FGFCS::GetDePos);
+
+  PropertyManager->Tie("fcs/rudder-pos-rad", this,ofRad, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
+  PropertyManager->Tie("fcs/rudder-pos-deg", this,ofDeg, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
+  PropertyManager->Tie("fcs/rudder-pos-norm", this,ofNorm, &FGFCS::GetDrPos, &FGFCS::SetDrPos);
+  PropertyManager->Tie("fcs/mag-rudder-pos-rad", this,ofMag, &FGFCS::GetDrPos);
+
+  PropertyManager->Tie("fcs/flap-pos-rad", this,ofRad, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
+  PropertyManager->Tie("fcs/flap-pos-deg", this,ofDeg, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
+  PropertyManager->Tie("fcs/flap-pos-norm", this,ofNorm, &FGFCS::GetDfPos, &FGFCS::SetDfPos);
+
+  PropertyManager->Tie("fcs/speedbrake-pos-rad", this,ofRad, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
+  PropertyManager->Tie("fcs/speedbrake-pos-deg", this,ofDeg, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
+  PropertyManager->Tie("fcs/speedbrake-pos-norm", this,ofNorm, &FGFCS::GetDsbPos, &FGFCS::SetDsbPos);
+  PropertyManager->Tie("fcs/mag-speedbrake-pos-rad", this,ofMag, &FGFCS::GetDsbPos);
+
+  PropertyManager->Tie("fcs/spoiler-pos-rad", this, ofRad, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
+  PropertyManager->Tie("fcs/spoiler-pos-deg", this, ofDeg, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
+  PropertyManager->Tie("fcs/spoiler-pos-norm", this, ofNorm, &FGFCS::GetDspPos, &FGFCS::SetDspPos);
+  PropertyManager->Tie("fcs/mag-spoiler-pos-rad", this, ofMag, &FGFCS::GetDspPos);
+
+  PropertyManager->Tie("gear/gear-pos-norm", this, &FGFCS::GetGearPos, &FGFCS::SetGearPos);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Technically, this function should probably bind propulsion type specific controls
+// rather than mixture and prop-advance.
+//
+
+void FGFCS::bindThrottle(unsigned int num)
+{
+  char tmp[80];
+
+  snprintf(tmp, 80, "fcs/throttle-cmd-norm[%u]",num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetThrottleCmd,
+                                        &FGFCS::SetThrottleCmd);
+  snprintf(tmp, 80, "fcs/throttle-pos-norm[%u]",num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetThrottlePos,
+                                        &FGFCS::SetThrottlePos);
+  snprintf(tmp, 80, "fcs/mixture-cmd-norm[%u]",num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetMixtureCmd,
+                                        &FGFCS::SetMixtureCmd);
+  snprintf(tmp, 80, "fcs/mixture-pos-norm[%u]",num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetMixturePos,
+                                        &FGFCS::SetMixturePos);
+  snprintf(tmp, 80, "fcs/advance-cmd-norm[%u]",num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropAdvanceCmd,
+                                        &FGFCS::SetPropAdvanceCmd);
+  snprintf(tmp, 80, "fcs/advance-pos-norm[%u]", num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropAdvance,
+                                        &FGFCS::SetPropAdvance);
+  snprintf(tmp, 80, "fcs/feather-cmd-norm[%u]", num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetFeatherCmd,
+                                        &FGFCS::SetFeatherCmd);
+  snprintf(tmp, 80, "fcs/feather-pos-norm[%u]", num);
+  PropertyManager->Tie( tmp, this, num, &FGFCS::GetPropFeather,
+                                        &FGFCS::SetPropFeather);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::bindModel(void)
+{
+  unsigned int i;
+  char tmp[80];
+
+  for (i=0; i<SteerPosDeg.size(); i++) {
+    if (GroundReactions->GetGearUnit(i)->GetSteerable()) {
+      snprintf(tmp,80,"fcs/steer-pos-deg[%u]",i);
+      PropertyManager->Tie( tmp, this, i, &FGFCS::GetSteerPosDeg, &FGFCS::SetSteerPosDeg);
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCS::unbind(FGPropertyManager *node)
+{
+  int N = node->nChildren();
+  for (int i=0; i<N; i++) {
+    if (node->getChild(i)->nChildren() ) {
+      unbind( (FGPropertyManager*)node->getChild(i) );
+    } else if ( node->getChild(i)->isTied() ) {
+      node->getChild(i)->untie();
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGFCS::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 2) { // Loader
+      cout << endl << "  Flight Control (" << Name << ")" << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGFCS" << endl;
+    if (from == 1) cout << "Destroyed:    FGFCS" << 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/models/FGFCS.h b/src/FDM/JSBSim/models/FGFCS.h
new file mode 100644 (file)
index 0000000..9a99ade
--- /dev/null
@@ -0,0 +1,506 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGFCS_H
+#define FGFCS_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#  else
+#    include <vector.h>
+#  endif
+#else
+#  include <vector>
+#endif
+
+#include <string>
+#include <models/flight_control/FGFCSComponent.h>
+#include <models/FGModel.h>
+#include <models/FGLGear.h>
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FCS "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+typedef enum { ofRad=0, ofDeg, ofNorm, ofMag , NForms} OutputForm;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates the Flight Control System (FCS) functionality.
+    This class owns and contains the list of FGFCSComponents
+    that define the control system for this aircraft. The config file for the
+    aircraft contains a description of the control path that starts at an input
+    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>
+    \<flight_control name="X-15 SAS">
+      \<channel>
+        \<component name="Pitch Trim Sum" type="SUMMER">
+           <input> fcs/elevator-cmd-norm </input>
+           <input> fcs/pitch-trim-cmd-norm </input>
+           <clipto>
+             <min>-1</min>
+             <max>1</max>
+           </clipto>
+        \</component>
+
+        \<component name="Pitch Command Scale" TYPE="AEROSURFACE_SCALE">
+          <input> fcs/pitch-trim-sum </input>
+          <limit>
+            <min> -50 </min>
+            <max>  50 </max>
+          </limit>
+        \</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".
+    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).  This continues until the
+    final component for an axis when the
+    \<output> element 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
+    @see FGXMLElement
+    @see FGGain
+    @see FGSummer
+    @see FGSwitch
+    @see FGGradient
+    @see FGFilter
+    @see FGDeadBand
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGFCS : public FGModel {
+
+public:
+  /** Constructor
+      @param Executive a pointer to the parent executive object */
+  FGFCS(FGFDMExec*);
+  /// Destructor
+  ~FGFCS();
+
+  /** Runs the Flight Controls model; called by the Executive
+      @return false if no error */
+  bool Run(void);
+
+  /// @name Pilot input command retrieval
+  //@{
+  /** Gets the aileron command.
+      @return aileron command in range from -1.0 - 1.0 */
+  inline double GetDaCmd(void) const { return DaCmd; }
+
+  /** Gets the elevator command.
+      @return elevator command in range from -1.0 - 1.0 */
+  inline double GetDeCmd(void) const { return DeCmd; }
+
+  /** Gets the rudder command.
+      @return rudder command in range from -1.0 - 1.0 */
+  inline double GetDrCmd(void) const { return DrCmd; }
+
+  /** Gets the steering command.
+      @return steering command in range from -1.0 - 1.0 */
+  inline double GetDsCmd(void) const { return DsCmd; }
+
+  /** Gets the flaps command.
+      @return flaps command in range from 0 to 1.0 */
+  inline double GetDfCmd(void) const { return DfCmd; }
+
+  /** Gets the speedbrake command.
+      @return speedbrake command in range from 0 to 1.0 */
+  inline double GetDsbCmd(void) const { return DsbCmd; }
+
+  /** Gets the spoiler command.
+      @return spoiler command in range from 0 to 1.0 */
+  inline double GetDspCmd(void) const { return DspCmd; }
+
+  /** Gets the throttle command.
+      @param engine engine ID number
+      @return throttle command in range from 0 - 1.0 for the given engine */
+  double GetThrottleCmd(int engine) const;
+
+  /** Gets the mixture command.
+      @param engine engine ID number
+      @return mixture command in range from 0 - 1.0 for the given engine */
+  inline double GetMixtureCmd(int engine) const { return MixtureCmd[engine]; }
+
+  /** Gets the prop pitch command.
+      @param engine engine ID number
+      @return pitch command in range from 0.0 - 1.0 for the given engine */
+  inline double GetPropAdvanceCmd(int engine) const { return PropAdvanceCmd[engine]; }
+
+  /** Gets the prop feather command.
+      @param engine engine ID number
+      @return feather command for the given engine (on / off)*/
+  inline bool GetFeatherCmd(int engine) const { return PropFeatherCmd[engine]; }
+
+  /** Gets the pitch trim command.
+      @return pitch trim command in range from -1.0 to 1.0 */
+  inline double GetPitchTrimCmd(void) const { return PTrimCmd; }
+
+  /** Gets the rudder trim command.
+      @return rudder trim command in range from -1.0 - 1.0 */
+  inline double GetYawTrimCmd(void) const { return YTrimCmd; }
+
+  /** Gets the aileron trim command.
+      @return aileron trim command in range from -1.0 - 1.0 */
+  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; }
+  //@}
+
+  /// @name Aerosurface position retrieval
+  //@{
+  /** Gets the left aileron position.
+      @return aileron position in radians */
+  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 )
+                         const { return DaRPos[form]; }
+
+  /** Gets the elevator position.
+      @return elevator position in radians */
+  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 )
+                         const { return DrPos[form]; }
+
+  /** Gets the speedbrake position.
+      @return speedbrake position in radians */
+  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 )
+                         const { return DspPos[form]; }
+
+  /** Gets the flaps position.
+      @return flaps position in radians */
+  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 range from 0 - 1.0 */
+  double GetThrottlePos(int engine) const;
+
+  /** Gets the mixture position.
+      @param engine engine ID number
+      @return mixture position for the given engine in range from 0 - 1.0 */
+  inline double GetMixturePos(int engine) const { return MixturePos[engine]; }
+
+  /** Gets the steering position.
+      @return steering position in degrees */
+  double GetSteerPosDeg(int gear) const { return SteerPosDeg[gear]; }
+
+  /** 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; }
+
+  /** Gets the prop pitch position.
+      @param engine engine ID number
+      @return prop pitch position for the given engine in range from 0 - 1.0 */
+  inline double GetPropAdvance(int engine) const { return PropAdvance[engine]; }
+
+  /** Gets the prop feather position.
+      @param engine engine ID number
+      @return prop fether for the given engine (on / off)*/
+  inline bool GetPropFeather(int engine) const { return PropFeather[engine]; }
+  //@}
+
+  /** Retrieves the State object pointer.
+      This is used by the FGFCS-owned components.
+      @return pointer to the State object */
+  inline FGState* GetState(void) { return State; }
+
+  /** Retrieves all component names for inclusion in output stream
+      @param delimeter either a tab or comma string depending on output type
+      @return a string containing the descriptive names for all components */
+  string GetComponentStrings(string delimeter);
+
+  /** Retrieves all component outputs for inclusion in output stream
+      @param delimeter either a tab or comma string depending on output type
+      @return a string containing the numeric values for the current set of
+      component outputs */
+  string GetComponentValues(string delimeter);
+
+  /// @name Pilot input command setting
+  //@{
+  /** Sets the aileron command
+      @param cmd aileron command */
+  inline void SetDaCmd( double cmd ) { DaCmd = cmd; }
+
+  /** Sets the elevator command
+      @param cmd elevator command in percent*/
+  inline void SetDeCmd(double cmd ) { DeCmd = cmd; }
+
+  /** Sets the rudder command
+      @param cmd rudder command in percent*/
+  inline void SetDrCmd(double cmd) { DrCmd = cmd; }
+
+  /** Sets the steering command
+      @param cmd steering command in percent*/
+  inline void SetDsCmd(double cmd) { DsCmd = cmd; }
+
+  /** Sets the flaps command
+      @param cmd flaps command in percent*/
+  inline void SetDfCmd(double cmd) { DfCmd = cmd; }
+
+  /** Sets the speedbrake command
+      @param cmd speedbrake command in percent*/
+  inline void SetDsbCmd(double cmd) { DsbCmd = cmd; }
+
+  /** Sets the spoilers command
+      @param cmd spoilers command in percent*/
+  inline void SetDspCmd(double cmd) { DspCmd = cmd; }
+
+  /** Sets the pitch trim command
+      @param cmd pitch trim command in percent*/
+  inline void SetPitchTrimCmd(double cmd) { PTrimCmd = cmd; }
+
+  /** Sets the rudder trim command
+      @param cmd rudder trim command in percent*/
+  inline void SetYawTrimCmd(double cmd) { YTrimCmd = cmd; }
+
+  /** Sets the aileron trim command
+      @param cmd aileron trim command in percent*/
+  inline void SetRollTrimCmd(double cmd) { RTrimCmd = cmd; }
+
+  /** Sets the throttle command for the specified engine
+      @param engine engine ID number
+      @param cmd throttle command in percent (0 - 100)*/
+  void SetThrottleCmd(int engine, double cmd);
+
+  /** Sets the mixture command for the specified engine
+      @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; }
+
+  /** Sets the propeller pitch command for the specified engine
+      @param engine engine ID number
+      @param cmd mixture command in percent (0.0 - 1.0)*/
+  void SetPropAdvanceCmd(int engine, double cmd);
+
+   /** Sets the propeller feather command for the specified engine
+      @param engine engine ID number
+      @param cmd feather (bool)*/
+  void SetFeatherCmd(int engine, bool cmd);
+  //@}
+
+  /// @name Aerosurface position setting
+  //@{
+  /** Sets the left aileron position
+      @param cmd left aileron position in radians*/
+  inline void SetDaLPos( int form , double pos );
+
+  /** Sets the right aileron position
+      @param cmd right aileron position in radians*/
+  inline void SetDaRPos( int form , double pos );
+
+  /** Sets the elevator position
+      @param cmd elevator position in radians*/
+  inline void SetDePos( int form , double pos );
+
+  /** Sets the rudder position
+      @param cmd rudder position in radians*/
+  inline void SetDrPos( int form , double pos );
+
+   /** Sets the flaps position
+      @param cmd flaps position in radians*/
+  inline void SetDfPos( int form , double pos );
+
+  /** Sets the speedbrake position
+      @param cmd speedbrake position in radians*/
+  inline void SetDsbPos( int form , double pos );
+
+  /** Sets the spoiler position
+      @param cmd spoiler position in radians*/
+  inline void SetDspPos( int form , double pos );
+
+  /** Sets the actual throttle setting for the specified engine
+      @param engine engine ID number
+      @param cmd throttle setting in percent (0 - 100)*/
+  void SetThrottlePos(int engine, double cmd);
+
+  /** Sets the actual mixture setting for the specified engine
+      @param engine engine ID number
+      @param cmd mixture setting in percent (0 - 100)*/
+  void SetMixturePos(int engine, double cmd);
+
+  /** Sets the steering position
+      @param cmd steering position in degrees*/
+  void SetSteerPosDeg(int gear, double pos) { SteerPosDeg[gear] = pos; }
+
+  /** Set the gear extend/retract position, defaults to down
+      @param gear position 0 up, 1 down       */
+   void SetGearPos(double gearpos) { GearPos = gearpos; }
+
+
+  /** Sets the actual prop pitch setting for the specified engine
+      @param engine engine ID number
+      @param cmd prop pitch setting in percent (0.0 - 1.0)*/
+  void SetPropAdvance(int engine, double cmd);
+
+  /** Sets the actual prop feather setting for the specified engine
+      @param engine engine ID number
+      @param cmd prop fether setting (bool)*/
+  void SetPropFeather(int engine, bool cmd);
+  //@}
+
+    /// @name Landing Gear brakes
+  //@{
+  /** Sets the left brake group
+      @param cmd brake setting in percent (0.0 - 1.0) */
+  void SetLBrake(double cmd) {LeftBrake = cmd;}
+
+  /** Sets the right brake group
+      @param cmd brake setting in percent (0.0 - 1.0) */
+  void SetRBrake(double cmd) {RightBrake = cmd;}
+
+  /** Sets the center brake group
+      @param cmd brake setting in percent (0.0 - 1.0) */
+  void SetCBrake(double cmd) {CenterBrake = cmd;}
+
+  /** Gets the brake for a specified group.
+      @param bg which brakegroup to retrieve the command for
+      @return the brake setting for the supplied brake group argument */
+  double GetBrake(FGLGear::BrakeGroup bg);
+  //@}
+
+  /** Loads the Flight Control System.
+      The FGAircraft instance is actually responsible for reading the config file
+      and calling the various Load() methods of the other systems, passing in
+      the XML Element instance pointer. Load() is called from FGAircraft.
+      @param el pointer to the Element instance
+      @return true if succesful */
+  bool Load(Element* el);
+
+  void AddThrottle(void);
+  void AddGear(void);
+
+  FGPropertyManager* GetPropertyManager(void) { return PropertyManager; }
+
+private:
+  double DaCmd, DeCmd, DrCmd, DsCmd, DfCmd, DsbCmd, DspCmd;
+  double DePos[NForms], DaLPos[NForms], DaRPos[NForms], DrPos[NForms];
+  double DfPos[NForms], DsbPos[NForms], DspPos[NForms];
+  double PTrimCmd, YTrimCmd, RTrimCmd;
+  vector <double> ThrottleCmd;
+  vector <double> ThrottlePos;
+  vector <double> MixtureCmd;
+  vector <double> MixturePos;
+  vector <double> PropAdvanceCmd;
+  vector <double> PropAdvance;
+  vector <bool> PropFeatherCmd;
+  vector <bool> PropFeather;
+  vector <double> SteerPosDeg;
+  double LeftBrake, RightBrake, CenterBrake; // Brake settings
+  double GearCmd,GearPos;
+
+  vector <FGFCSComponent*> FCSComponents;
+  vector <FGFCSComponent*> APComponents;
+  vector <double*> interface_properties;
+  vector <FGFCSComponent*> sensors;
+  void bind(void);
+  void bindModel(void);
+  void bindThrottle(unsigned int);
+  void unbind(FGPropertyManager *node);
+  void Debug(int from);
+};
+}
+
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGGroundReactions.cpp b/src/FDM/JSBSim/models/FGGroundReactions.cpp
new file mode 100644 (file)
index 0000000..1ed71ab
--- /dev/null
@@ -0,0 +1,272 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGGroundReactions.cpp
+ Author:       Jon S. Berndt
+ Date started: 09/13/00
+ Purpose:      Encapsulates the ground reaction forces (gear and collision)
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+09/13/00   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <sstream>
+#include <iomanip>
+
+#include "FGGroundReactions.h"
+#include <input_output/FGPropertyManager.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_GROUNDREACTIONS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex)
+{
+  Name = "FGGroundReactions";
+
+  bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGGroundReactions::~FGGroundReactions(void)
+{
+  for (int i=0; i<lGear.size();i++) lGear[i].unbind();
+  lGear.clear();
+
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGGroundReactions::Run(void)
+{
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  vForces.InitMatrix();
+  vMoments.InitMatrix();
+
+  if ( Propagate->GetDistanceAGL() < 300.0 ) { // Only execute gear code below 300 feet
+    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.
+    // The gear ::Run() method is called several times - once for each gear.
+    // Perhaps there is some commonality for things which only need to be
+    // calculated once.
+
+    while (iGear != lGear.end()) {
+      vForces  += iGear->Force();
+      vMoments += iGear->Moment();
+      iGear++;
+    }
+
+  }
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGGroundReactions::GetWOW(void)
+{
+  bool result = false;
+  for (int i=0; i<lGear.size(); i++) {
+    if (lGear[i].IsBogey() && lGear[i].GetWOW()) {
+      result = true;
+      break;
+    }
+  }
+  return result;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGGroundReactions::Load(Element* el)
+{
+  int num=0;
+
+  Debug(2);
+
+  Element* contact_element = el->FindElement("contact");
+  while (contact_element) {
+    lGear.push_back(FGLGear(contact_element, FDMExec, num++));
+    FCS->AddGear(); // make the FCS aware of the landing gear
+    contact_element = el->FindNextElement("contact");
+  }
+
+  for (int i=0; i<lGear.size();i++) lGear[i].bind();
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGGroundReactions::GetGroundReactionStrings(string delimeter)
+{
+  std::ostringstream buf;
+
+  for (unsigned int i=0;i<lGear.size();i++) {
+    string name = lGear[i].GetName();
+    buf << name << "_WOW" << delimeter
+        << name << "_stroke" << delimeter
+        << name << "_strokeVel" << delimeter
+        << name << "_CompressForce" << delimeter
+        << name << "_WhlSideForce" << delimeter
+        << name << "_WhlVelVecX" << delimeter
+        << name << "_WhlVelVecY" << delimeter
+        << name << "_WhlRollForce" << delimeter
+        << name << "_BodyXForce" << delimeter
+        << name << "_BodyYForce" << delimeter
+        << name << "_WhlSlipDegrees" << delimeter;
+  }
+
+  buf << "TotalGearForce_X" << delimeter
+      << "TotalGearForce_Y" << delimeter
+      << "TotalGearForce_Z" << delimeter
+      << "TotalGearMoment_L" << delimeter
+      << "TotalGearMoment_M" << delimeter
+      << "TotalGearMoment_N";
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGGroundReactions::GetGroundReactionValues(string delimeter)
+{
+  std::ostringstream buf;
+
+  for (unsigned int i=0;i<lGear.size();i++) {
+    FGLGear& gear = lGear[i];
+    buf << (gear.GetWOW() ? "1, " : "0, ")
+        << setprecision(5) << gear.GetCompLen() << delimeter
+        << setprecision(6) << gear.GetCompVel() << delimeter
+        << setprecision(10) << gear.GetCompForce() << delimeter
+        << setprecision(6) << gear.GetWheelVel(eX) << delimeter
+        << gear.GetWheelVel(eY) << delimeter
+        << gear.GetWheelSideForce() << delimeter
+        << gear.GetWheelRollForce() << delimeter
+        << gear.GetBodyXForce() << delimeter
+        << gear.GetBodyYForce() << delimeter
+        << gear.GetWheelSlipAngle() << delimeter;
+  }
+
+  buf << vForces(eX) << delimeter
+      << vForces(eY) << delimeter
+      << vForces(eZ) << delimeter
+      << vMoments(eX) << delimeter
+      << vMoments(eY) << delimeter
+      << vMoments(eZ);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGGroundReactions::bind(void)
+{
+  typedef double (FGGroundReactions::*PMF)(int) const;
+  PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits);
+  PropertyManager->Tie("moments/l-gear-lbsft", this, eL, (PMF)&FGGroundReactions::GetMoments);
+  PropertyManager->Tie("moments/m-gear-lbsft", this, eM, (PMF)&FGGroundReactions::GetMoments);
+  PropertyManager->Tie("moments/n-gear-lbsft", this, eN, (PMF)&FGGroundReactions::GetMoments);
+  PropertyManager->Tie("forces/fbx-gear-lbs", this, eX, (PMF)&FGGroundReactions::GetForces);
+  PropertyManager->Tie("forces/fby-gear-lbs", this, eY, (PMF)&FGGroundReactions::GetForces);
+  PropertyManager->Tie("forces/fbz-gear-lbs", this, eZ, (PMF)&FGGroundReactions::GetForces);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGGroundReactions::unbind(void)
+{
+  PropertyManager->Untie("gear/num-units");
+  PropertyManager->Untie("moments/l-gear-lbsft");
+  PropertyManager->Untie("moments/m-gear-lbsft");
+  PropertyManager->Untie("moments/n-gear-lbsft");
+  PropertyManager->Untie("forces/fbx-gear-lbs");
+  PropertyManager->Untie("forces/fby-gear-lbs");
+  PropertyManager->Untie("forces/fbz-gear-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
+//       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 FGGroundReactions::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 2) { // Loading
+      cout << endl << "  Ground Reactions: " << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
+    if (from == 1) cout << "Destroyed:    FGGroundReactions" << 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/models/FGGroundReactions.h b/src/FDM/JSBSim/models/FGGroundReactions.h
new file mode 100644 (file)
index 0000000..c67f546
--- /dev/null
@@ -0,0 +1,114 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGGroundReactions.h
+ Author:       Jon S. Berndt
+ Date started: 09/13/00
+
+ ------------- 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
+--------------------------------------------------------------------------------
+09/13/00   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGGROUNDREACTIONS_H
+#define FGGROUNDREACTIONS_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#  else
+#    include <vector.h>
+#  endif
+#else
+#  include <vector>
+#endif
+
+#include "FGModel.h"
+#include "FGLGear.h"
+#include <math/FGColumnVector3.h>
+#include <input_output/FGXMLElement.h>
+
+#define ID_GROUNDREACTIONS "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Manages ground reactions modeling.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGGroundReactions : public FGModel
+{
+public:
+  FGGroundReactions(FGFDMExec*);
+  ~FGGroundReactions(void);
+
+  bool Run(void);
+  bool Load(Element* el);
+  FGColumnVector3& GetForces(void) {return vForces;}
+  double GetForces(int idx) const {return vForces(idx);}
+  FGColumnVector3& GetMoments(void) {return vMoments;}
+  double GetMoments(int idx) const {return vMoments(idx);}
+  string GetGroundReactionStrings(string delimeter);
+  string GetGroundReactionValues(string delimeter);
+  bool GetWOW(void);
+
+  inline int GetNumGearUnits(void) const { return lGear.size(); }
+
+  /** Gets a gear instance
+      @param gear index of gear instance
+      @return a pointer to the FGLGear instance of the gear unit requested */
+  inline FGLGear* GetGearUnit(int gear) { return &(lGear[gear]); }
+
+  void bind(void);
+  void unbind(void);
+
+private:
+  vector <FGLGear> lGear;
+  FGColumnVector3 vForces;
+  FGColumnVector3 vMoments;
+  FGColumnVector3 vMaxStaticGrip;
+  FGColumnVector3 vMaxMomentResist;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGInertial.cpp b/src/FDM/JSBSim/models/FGInertial.cpp
new file mode 100644 (file)
index 0000000..c86ba67
--- /dev/null
@@ -0,0 +1,134 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGInertial.cpp
+ Author:       Jon S. Berndt
+ Date started: 09/13/00
+ Purpose:      Encapsulates the inertial frame forces (coriolis and centrifugal)
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+09/13/00   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGInertial.h"
+#include "FGPropagate.h"
+#include "FGState.h"
+#include "FGMassBalance.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_INERTIAL;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGInertial::FGInertial(FGFDMExec* fgex) : FGModel(fgex)
+{
+  Name = "FGInertial";
+
+  // Defaults
+  RotationRate    = 0.00007272205217;
+  GM              = 14.06252720E15;
+  RadiusReference = 20925650.00;
+  gAccelReference = GM/(RadiusReference*RadiusReference);
+  gAccel          = GM/(RadiusReference*RadiusReference);
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGInertial::~FGInertial(void)
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGInertial::Run(void)
+{
+  // Fast return if we have nothing to do ...
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  // Gravitation accel
+  double r = Propagate->GetRadius();
+  gAccel = GetGAccel(r);
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGInertial::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: FGInertial" << endl;
+    if (from == 1) cout << "Destroyed:    FGInertial" << 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/models/FGInertial.h b/src/FDM/JSBSim/models/FGInertial.h
new file mode 100644 (file)
index 0000000..9433af1
--- /dev/null
@@ -0,0 +1,101 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGInertial.h
+ Author:       Jon S. Berndt
+ Date started: 09/13/00
+
+ ------------- 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
+--------------------------------------------------------------------------------
+09/13/00   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGINERTIAL_H
+#define FGINERTIAL_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#  else
+#    include <vector.h>
+#  endif
+#else
+#  include <vector>
+#endif
+
+#include "FGModel.h"
+#include <math/FGColumnVector3.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_INERTIAL "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models inertial forces (e.g. centripetal and coriolis accelerations).
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGInertial : public FGModel {
+
+public:
+  FGInertial(FGFDMExec*);
+  ~FGInertial(void);
+
+  bool Run(void);
+  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;}
+
+private:
+  double gAccel;
+  double gAccelReference;
+  double RadiusReference;
+  double RotationRate;
+  double GM;
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/models/FGInput.cpp b/src/FDM/JSBSim/models/FGInput.cpp
new file mode 100755 (executable)
index 0000000..363c345
--- /dev/null
@@ -0,0 +1,269 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGInput.cpp
+ Author:       Jon Berndt
+ Date started: 12/02/98
+ Purpose:      Manage output of sim parameters to file or stdout
+ 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
+ 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 is the place where you create output routines to dump data for perusal
+later.
+
+HISTORY
+--------------------------------------------------------------------------------
+12/02/98   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGInput.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+
+#include <fstream>
+#include <iomanip>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_INPUT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGInput::FGInput(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGInput";
+  sFirstPass = dFirstPass = true;
+  socket = 0;
+  port = 0;
+  enabled = true;
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGInput::~FGInput()
+{
+  if (socket) delete socket;
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// This function handles accepting input commands from the socket interface.
+//
+
+bool FGInput::Run(void)
+{
+  string line, token, info_string;
+  int start=0, string_start=0, string_end=0;
+  int token_start=0, token_end=0;
+  char buf[100];
+  double value=0;
+  FGPropertyManager* node=0;
+
+  if (FGModel::Run()) return true; // fast exit if nothing to do
+  if (port == 0) return true; // Do nothing here if port not defined
+  // This model DOES execute if "Exec->Holding"
+
+  data = socket->Receive(); // get socket transmission if present
+
+  if (data.size() > 0) {
+    // parse lines
+    while (1) {
+      string_start = data.find_first_not_of("\r\n", start);
+      if (string_start == string::npos) break;
+      string_end = data.find_first_of("\r\n", string_start);
+      if (string_end == string::npos) break;
+      line = data.substr(string_start, string_end-string_start);
+      if (line.size() == 0) break;
+
+      // now parse individual line
+      token_start = line.find_first_not_of(" ", 0);
+      token_end = line.find_first_of(" ", token_start);
+      token = line.substr(token_start, token_end - token_start);
+
+      if (token == "set" || token == "SET" ) {                   // SET PROPERTY
+
+        token_start = line.find_first_not_of(" ", token_end);
+        token_end = line.find_first_of(" ", token_start);
+        token = line.substr(token_start, token_end-token_start);
+        node = PropertyManager->GetNode(token);
+        if (node == 0) socket->Reply("Unknown property\n");
+        else {
+          token_start = line.find_first_not_of(" ", token_end);
+          token_end = line.find_first_of(" ", token_start);
+          token = line.substr(token_start, token_end-token_start);
+          value = atof(token.c_str());
+          node->setDoubleValue(value);
+        }
+
+      } else if (token == "get" || token == "GET") {             // GET PROPERTY
+
+        token_start = line.find_first_not_of(" ", token_end);
+        if (token_start == string::npos) {
+          socket->Reply("No property argument supplied.\n");
+          break;
+        } else {
+          token = line.substr(token_start, line.size()-token_start);
+        }
+        try {
+          node = PropertyManager->GetNode(token);
+        } catch(...) {
+          socket->Reply("Badly formed property query\n");
+          break;
+        }
+        if (node == 0) {
+          if (FDMExec->Holding()) { // if holding can query property list
+            string query = FDMExec->QueryPropertyCatalog(token);
+            socket->Reply(query);
+          } else {
+            socket->Reply("Must be in HOLD to search properties\n");
+          }
+        } else if (node > 0) {
+          sprintf(buf, "%s = %12.6f\n", token.c_str(), node->getDoubleValue());
+          socket->Reply(buf);
+        }
+
+      } else if (token == "hold" || token == "HOLD") {                  // PAUSE
+
+        FDMExec->Hold();
+
+      } else if (token == "resume" || token == "RESUME") {             // RESUME
+
+        FDMExec->Resume();
+
+      } else if (token == "quit" || token == "QUIT") {                   // QUIT
+
+        // close the socket connection
+        socket->Reply("");
+        socket->Close();
+
+      } else if (token == "info" || token == "INFO") {                   // INFO
+
+        // get info about the sim run and/or aircraft, etc.
+        sprintf(buf, "%8.3f\0", State->Getsim_time());
+        info_string  = "JSBSim version: " + JSBSim_version + "\n";
+        info_string += "Config File version: " + needed_cfg_version + "\n";
+        info_string += "Aircraft simulated: " + Aircraft->GetAircraftName() + "\n";
+        info_string += "Simulation time: " + string(buf) + "\n";
+        socket->Reply(info_string);
+
+      } else if (token == "help" || token == "HELP") {                   // HELP
+
+        socket->Reply(
+        " JSBSim Server commands:\n\n"
+        "   get {property name}\n"
+        "   set {property name} {value}\n"
+        "   hold\n"
+        "   resume\n"
+        "   help\n"
+        "   quit\n"
+        "   info\n\n");
+
+      } else {
+        socket->Reply(string("Unknown command: ") +  token + string("\n"));
+      }
+
+      start = string_end;
+    }
+  }
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGInput::Load(Element* element)
+{
+  string type="", parameter="";
+  string name="", fname="";
+  string property;
+
+  port = element->GetAttributeValueAsNumber("port");
+  if (port == 0) {
+    cerr << endl << "No port assigned in input element" << endl;
+  } else {
+    socket = new FGfdmSocket(port);
+  }
+
+  Debug(2);
+
+  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 FGInput::Debug(int from)
+{
+  string scratch="";
+
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+    }
+    if (from == 2) {
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGInput" << endl;
+    if (from == 1) cout << "Destroyed:    FGInput" << 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/models/FGInput.h b/src/FDM/JSBSim/models/FGInput.h
new file mode 100755 (executable)
index 0000000..071b48a
--- /dev/null
@@ -0,0 +1,107 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGInput.h
+ Author:       Jon Berndt
+ Date started: 12/2/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 FGINPUT_H
+#define FGINPUT_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGModel.h"
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_IOSTREAM
+#  include STL_FSTREAM
+#else
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <iostream.h>
+#    include <fstream.h>
+#  else
+#    include <iostream>
+#    include <fstream>
+#  endif
+#endif
+
+#include <input_output/FGfdmSocket.h>
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_INPUT "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Handles simulation input.
+ */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGInput : public FGModel
+{
+public:
+  FGInput(FGFDMExec*);
+  ~FGInput();
+
+  bool Run(void);
+
+  void SetType(string);
+  inline void Enable(void) { enabled = true; }
+  inline void Disable(void) { enabled = false; }
+  inline bool Toggle(void) {enabled = !enabled; return enabled;}
+  bool Load(Element* el);
+
+private:
+  bool sFirstPass, dFirstPass, enabled;
+  unsigned int port;
+  FGfdmSocket* socket;
+  string data;
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp
new file mode 100644 (file)
index 0000000..62fe8cc
--- /dev/null
@@ -0,0 +1,694 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGLGear.cpp
+ Author:       Jon S. Berndt
+               Norman H. Princen
+ Date started: 11/18/99
+ Purpose:      Encapsulates the landing gear elements
+ 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
+--------------------------------------------------------------------------------
+
+HISTORY
+--------------------------------------------------------------------------------
+11/18/99   JSB   Created
+01/30/01   NHP   Extended gear model to properly simulate steering and braking
+
+/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGLGear.h"
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+GLOBAL DATA
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_LGEAR;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) : Exec(fdmex),
+                 GearNumber(number)
+{
+  Element *force_table=0;
+  string force_type="";
+
+  kSpring = bDamp = bDampRebound = dynamicFCoeff = staticFCoeff = rollingFCoeff = maxSteerAngle = 0;
+  sSteerType = sBrakeGroup = sSteerType = "";
+  isRetractable = 0;
+
+  name = el->GetAttributeValue("name");
+  sContactType = el->GetAttributeValue("type");
+  if (el->FindElement("spring_coeff"))
+    kSpring = el->FindElementValueAsNumberConvertTo("spring_coeff", "LBS/FT");
+  if (el->FindElement("damping_coeff"))
+    bDamp   = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT/SEC");
+
+  if (el->FindElement("damping_coeff_rebound"))
+    bDampRebound   = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT/SEC");
+  else
+    bDampRebound   = bDamp;
+
+  if (el->FindElement("dynamic_friction"))
+    dynamicFCoeff = el->FindElementValueAsNumber("dynamic_friction");
+  if (el->FindElement("static_friction"))
+    staticFCoeff = el->FindElementValueAsNumber("static_friction");
+  if (el->FindElement("rolling_friction"))
+    rollingFCoeff = el->FindElementValueAsNumber("rolling_friction");
+  if (el->FindElement("max_steer"))
+    maxSteerAngle = el->FindElementValueAsNumberConvertTo("max_steer", "DEG");
+  if (el->FindElement("retractable"))
+    isRetractable = (int)el->FindElementValueAsNumber("retractable");
+
+  ForceY_Table = 0;
+  force_table = el->FindElement("table");
+  while (force_table) {
+    force_type = force_table->GetAttributeValue("type");
+    if (force_type == "CORNERING_COEFF") {
+      ForceY_Table = new FGTable(Exec->GetPropertyManager(), force_table);
+    } else {
+      cerr << "Undefined force table for " << name << " contact point" << endl;
+    }
+    force_table = el->FindNextElement("table");
+  }
+
+  sBrakeGroup = el->FindElementValue("brake_group");
+
+  if (maxSteerAngle == 360) sSteerType = "CASTERED";
+  else if (maxSteerAngle == 0.0) sSteerType = "FIXED";
+  else sSteerType = "STEERABLE";
+
+  Element* element = el->FindElement("location");
+  if (element) vXYZ = element->FindElementTripletConvertTo("IN");
+  else {cerr << "No location given for contact " << name << endl; exit(-1);}
+
+  if      (sBrakeGroup == "LEFT"  ) eBrakeGrp = bgLeft;
+  else if (sBrakeGroup == "RIGHT" ) eBrakeGrp = bgRight;
+  else if (sBrakeGroup == "CENTER") eBrakeGrp = bgCenter;
+  else if (sBrakeGroup == "NOSE"  ) eBrakeGrp = bgNose;
+  else if (sBrakeGroup == "TAIL"  ) eBrakeGrp = bgTail;
+  else if (sBrakeGroup == "NONE"  ) eBrakeGrp = bgNone;
+  else if (sBrakeGroup.empty()    ) {eBrakeGrp = bgNone;
+                                     sBrakeGroup = "NONE (defaulted)";}
+  else {
+    cerr << "Improper braking group specification in config file: "
+         << sBrakeGroup << " is undefined." << endl;
+  }
+
+  if      (sSteerType == "STEERABLE") eSteerType = stSteer;
+  else if (sSteerType == "FIXED"    ) eSteerType = stFixed;
+  else if (sSteerType == "CASTERED" ) eSteerType = stCaster;
+  else if (sSteerType.empty()       ) {eSteerType = stFixed;
+                                       sSteerType = "FIXED (defaulted)";}
+  else {
+    cerr << "Improper steering type specification in config file: "
+         << sSteerType << " is undefined." << endl;
+  }
+
+  GearUp = false;
+  GearDown = true;
+  Servicable = true;
+
+// Add some AI here to determine if gear is located properly according to its
+// brake group type ??
+
+  State       = Exec->GetState();
+  Aircraft    = Exec->GetAircraft();
+  Propagate   = Exec->GetPropagate();
+  Auxiliary   = Exec->GetAuxiliary();
+  FCS         = Exec->GetFCS();
+  MassBalance = Exec->GetMassBalance();
+
+  WOW = lastWOW = true; // should the value be initialized to true?
+  ReportEnable = true;
+  FirstContact = false;
+  StartedGroundRun = false;
+  TakeoffReported = LandingReported = false;
+  LandingDistanceTraveled = TakeoffDistanceTraveled = TakeoffDistanceTraveled50ft = 0.0;
+  MaximumStrutForce = MaximumStrutTravel = 0.0;
+  SideForce = RollingForce = 0.0;
+  SinkRate = GroundSpeed = 0.0;
+
+  vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);
+
+  vLocalGear = Propagate->GetTb2l() * vWhlBodyVec;
+
+  compressLength  = 0.0;
+  compressSpeed   = 0.0;
+  brakePct        = 0.0;
+  maxCompLen      = 0.0;
+
+  WheelSlip = last_WheelSlip = 0.0;
+  TirePressureNorm = 1.0;
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGLGear::FGLGear(const FGLGear& lgear)
+{
+  GearNumber = lgear.GearNumber;
+  State    = lgear.State;
+  Aircraft = lgear.Aircraft;
+  Propagate = lgear.Propagate;
+  Auxiliary = lgear.Auxiliary;
+  Exec     = lgear.Exec;
+  FCS      = lgear.FCS;
+  MassBalance = lgear.MassBalance;
+
+  vXYZ = lgear.vXYZ;
+  vMoment = lgear.vMoment;
+  vWhlBodyVec = lgear.vWhlBodyVec;
+  vLocalGear = lgear.vLocalGear;
+
+  WOW                = lgear.WOW;
+  lastWOW            = lgear.lastWOW;
+  ReportEnable       = lgear.ReportEnable;
+  FirstContact       = lgear.FirstContact;
+  StartedGroundRun   = lgear.StartedGroundRun;
+  LandingDistanceTraveled   = lgear.LandingDistanceTraveled;
+  TakeoffDistanceTraveled   = lgear.TakeoffDistanceTraveled;
+  TakeoffDistanceTraveled50ft   = lgear.TakeoffDistanceTraveled50ft;
+  MaximumStrutForce  = lgear.MaximumStrutForce;
+  MaximumStrutTravel = lgear.MaximumStrutTravel;
+  SideForce          = lgear.SideForce;
+  RollingForce       = lgear.RollingForce;
+
+  kSpring         = lgear.kSpring;
+  bDamp           = lgear.bDamp;
+  bDampRebound    = lgear.bDampRebound;
+  compressLength  = lgear.compressLength;
+  compressSpeed   = lgear.compressSpeed;
+  staticFCoeff    = lgear.staticFCoeff;
+  dynamicFCoeff   = lgear.dynamicFCoeff;
+  rollingFCoeff   = lgear.rollingFCoeff;
+  brakePct        = lgear.brakePct;
+  maxCompLen      = lgear.maxCompLen;
+  SinkRate        = lgear.SinkRate;
+  GroundSpeed     = lgear.GroundSpeed;
+  LandingReported = lgear.LandingReported;
+  TakeoffReported = lgear.TakeoffReported;
+  name            = lgear.name;
+  sSteerType      = lgear.sSteerType;
+  sRetractable    = lgear.sRetractable;
+  sContactType    = lgear.sContactType;
+  sBrakeGroup     = lgear.sBrakeGroup;
+  eSteerType      = lgear.eSteerType;
+  eBrakeGrp       = lgear.eBrakeGrp;
+  maxSteerAngle   = lgear.maxSteerAngle;
+  isRetractable   = lgear.isRetractable;
+  GearUp          = lgear.GearUp;
+  GearDown        = lgear.GearDown;
+  WheelSlip       = lgear.WheelSlip;
+  TirePressureNorm = lgear.TirePressureNorm;
+  Servicable      = lgear.Servicable;
+  ForceY_Table    = lgear.ForceY_Table;
+  CosWheel        = lgear.CosWheel;
+  SinWheel        = lgear.SinWheel;
+  In              = lgear.In;
+  prevIn          = lgear.prevIn;
+  prevOut         = lgear.prevOut;
+  slipIn          = lgear.slipIn;
+  last_SlipIn     = lgear.last_SlipIn;
+  last_WheelSlip  = lgear.last_WheelSlip;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGLGear::~FGLGear()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGLGear::Force(void)
+{
+  FGColumnVector3 normal, cvel;
+  FGLocation contact, gearLoc;
+  double t = Exec->GetState()->Getsim_time();
+
+  vForce.InitMatrix();
+  vMoment.InitMatrix();
+
+  if (isRetractable) ComputeRetractionState();
+
+  if (GearUp) return vForce;
+
+  vWhlBodyVec = MassBalance->StructuralToBody(vXYZ); // Get wheel in body frame
+  vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location
+
+  gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear);
+  compressLength = -Exec->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel);
+
+  // The compression length is measured in the Z-axis, only, at this time.
+
+  if (compressLength > 0.00) {
+
+    WOW = true;
+
+    // [The next equation should really use the vector to the contact patch of
+    // the tire including the strut compression and not the original vWhlBodyVec.]
+
+    vWhlVelVec      =  Propagate->GetTb2l() * (Propagate->GetPQR() * vWhlBodyVec);
+    vWhlVelVec     +=  Propagate->GetVel() - cvel;
+    compressSpeed   =  vWhlVelVec(eZ);
+
+    InitializeReporting();
+    ComputeBrakeForceCoefficient();
+    ComputeSteeringAngle();
+    ComputeSlipAngle();
+    ComputeSideForceCoefficient();
+    ComputeVerticalStrutForce();
+
+    // Compute the forces in the wheel ground plane.
+
+    RollingForce = (1.0 - TirePressureNorm) * 30
+                   + vLocalForce(eZ) * BrakeFCoeff * (RollingWhlVel>=0?1.0:-1.0);
+    SideForce    = vLocalForce(eZ) * FCoeff;
+
+    // Transform these forces back to the local reference frame.
+
+    vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel;
+    vLocalForce(eY) = SideForce*CosWheel    + RollingForce*SinWheel;
+
+    // Transform the forces back to the body frame and compute the moment.
+
+    vForce  = Propagate->GetTl2b() * vLocalForce;
+
+    // Lag and attenuate the XY-plane forces dependent on velocity
+
+    double RFRV = 0.015; // Rolling force relaxation velocity
+    double SFRV = 0.25;  // Side force relaxation velocity
+    double dT = State->Getdt()*Exec->GetGroundReactions()->GetRate();
+
+    In = vForce;
+    vForce(eX) = (0.25)*(In(eX) + prevIn(eX)) + (0.50)*prevOut(eX);
+    vForce(eY) = (0.15)*(In(eY) + prevIn(eY)) + (0.70)*prevOut(eY);
+    prevOut = vForce;
+    prevIn = In;
+
+    if (fabs(RollingWhlVel) <= RFRV) vForce(eX) *= fabs(RollingWhlVel)/RFRV;
+    if (fabs(SideWhlVel) <= SFRV) vForce(eY) *= fabs(SideWhlVel)/SFRV;
+
+    vMoment = vWhlBodyVec * vForce;
+
+  } else { // Gear is NOT compressed
+
+    WOW = false;
+    compressLength = 0.0;
+
+    // Return to neutral position between 1.0 and 0.8 gear pos.
+    SteerAngle *= max(FCS->GetGearPos()-0.8, 0.0)/0.2;
+
+    ResetReporting();
+  }
+
+  ReportTakeoffOrLanding();
+  CrashDetect();
+
+  return vForce;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLGear::ComputeRetractionState(void)
+{
+  if (FCS->GetGearPos() < 0.01) {
+    GearUp   = true;
+    GearDown = false;
+  } else if (FCS->GetGearPos() > 0.99) {
+    GearDown = true;
+    GearUp   = false;
+  } else {
+    GearUp   = false;
+    GearDown = false;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLGear::ComputeSlipAngle(void)
+{
+  double dT = State->Getdt()*Exec->GetGroundReactions()->GetRate();
+
+  // Transform the wheel velocities from the local axis system to the wheel axis system.
+
+  RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;
+  SideWhlVel    = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;
+
+  // Calculate tire slip angle.
+
+  if (fabs(RollingWhlVel) < 0.1 && fabs(SideWhlVel) < 0.01) {
+    WheelSlip = -SteerAngle*radtodeg;
+  } else {
+    WheelSlip = atan2(SideWhlVel, fabs(RollingWhlVel))*radtodeg;
+  }
+  slipIn = WheelSlip;
+  WheelSlip = (0.46)*(slipIn + last_SlipIn) + (0.08)*last_WheelSlip;
+  last_WheelSlip = WheelSlip;
+  last_SlipIn = slipIn;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Compute the steering angle in any case.
+// This will also make sure that animations will look right.
+
+void FGLGear::ComputeSteeringAngle(void)
+{
+  switch (eSteerType) {
+  case stSteer:
+    SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber);
+    break;
+  case stFixed:
+    SteerAngle = 0.0;
+    break;
+  case stCaster:
+    // This is not correct for castering gear. Should make steer angle parallel
+    // to the actual velocity vector of the wheel, given aircraft velocity vector
+    // and omega.
+    SteerAngle = 0.0;
+    break;
+  default:
+    cerr << "Improper steering type membership detected for this gear." << endl;
+    break;
+  }
+
+  SinWheel      = sin(Propagate->GetEuler(ePsi) + SteerAngle);
+  CosWheel      = cos(Propagate->GetEuler(ePsi) + SteerAngle);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Reset reporting functionality after takeoff
+
+void FGLGear::ResetReporting(void)
+{
+  if (Propagate->GetDistanceAGL() > 200.0) {
+    FirstContact = false;
+    StartedGroundRun = false;
+    LandingReported = false;
+    LandingDistanceTraveled = 0.0;
+    MaximumStrutForce = MaximumStrutTravel = 0.0;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLGear::InitializeReporting(void)
+{
+  // If this is the first time the wheel has made contact, remember some values
+  // for later printout.
+
+  if (!FirstContact) {
+    FirstContact  = true;
+    SinkRate      =  compressSpeed;
+    GroundSpeed   =  Propagate->GetVel().Magnitude();
+    TakeoffReported = false;
+  }
+
+  // If the takeoff run is starting, initialize.
+
+  if ((Propagate->GetVel().Magnitude() > 0.1) &&
+      (FCS->GetBrake(bgLeft) == 0) &&
+      (FCS->GetBrake(bgRight) == 0) &&
+      (FCS->GetThrottlePos(0) == 1) && !StartedGroundRun)
+  {
+    TakeoffDistanceTraveled = 0;
+    TakeoffDistanceTraveled50ft = 0;
+    StartedGroundRun = true;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Takeoff and landing reporting functionality
+
+void FGLGear::ReportTakeoffOrLanding(void)
+{
+  double deltaT = State->Getdt()*Exec->GetGroundReactions()->GetRate();
+
+  if (FirstContact) LandingDistanceTraveled += Auxiliary->GetVground()*deltaT;
+
+  if (StartedGroundRun) {
+     TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*deltaT;
+    if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*deltaT;
+  }
+
+  if (ReportEnable && Auxiliary->GetVground() <= 0.05 && !LandingReported) {
+    if (debug_lvl > 0) Report(erLand);
+  }
+
+  if (ReportEnable && !TakeoffReported &&
+     (vLocalGear(eZ) - Propagate->GetDistanceAGL()) < -50.0)
+  {
+    if (debug_lvl > 0) Report(erTakeoff);
+  }
+
+  if (lastWOW != WOW) PutMessage("GEAR_CONTACT: " + name, WOW);
+  lastWOW = WOW;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Crash detection logic (really out-of-bounds detection)
+
+void FGLGear::CrashDetect(void)
+{
+  if (compressLength > 500.0 ||
+      vForce.Magnitude() > 100000000.0 ||
+      vMoment.Magnitude() > 5000000000.0 ||
+      SinkRate > 1.4666*30)
+  {
+    PutMessage("Crash Detected: Simulation FREEZE.");
+    State->SuspendIntegration();
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// The following needs work regarding friction coefficients and braking and
+// steering The BrakeFCoeff formula assumes that an anti-skid system is used.
+// It also assumes that we won't be turning and braking at the same time.
+// Will fix this later.
+// [JSB] The braking force coefficients include normal rolling coefficient +
+// a percentage of the static friction coefficient based on braking applied.
+
+void FGLGear::ComputeBrakeForceCoefficient(void)
+{
+  switch (eBrakeGrp) {
+  case bgLeft:
+    BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
+                     staticFCoeff*FCS->GetBrake(bgLeft) );
+    break;
+  case bgRight:
+    BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
+                     staticFCoeff*FCS->GetBrake(bgRight) );
+    break;
+  case bgCenter:
+    BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
+                     staticFCoeff*FCS->GetBrake(bgCenter) );
+    break;
+  case bgNose:
+    BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
+                     staticFCoeff*FCS->GetBrake(bgCenter) );
+    break;
+  case bgTail:
+    BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
+                     staticFCoeff*FCS->GetBrake(bgCenter) );
+    break;
+  case bgNone:
+    BrakeFCoeff =  rollingFCoeff;
+    break;
+  default:
+    cerr << "Improper brake group membership detected for this gear." << endl;
+    break;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// 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 (similar to Pacejka).  Will fix this later.
+
+void FGLGear::ComputeSideForceCoefficient(void)
+{
+  if (ForceY_Table) {
+
+    FCoeff = ForceY_Table->GetValue(WheelSlip);
+
+  } else {
+
+    if (fabs(WheelSlip) <= 10.0) {
+      FCoeff = staticFCoeff*WheelSlip/10.0;
+    } else if (fabs(WheelSlip) <= 40.0) {
+      FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 10.0)/10.0
+                + staticFCoeff*(40.0 - fabs(WheelSlip))/10.0)*(WheelSlip>=0?1.0:-1.0);
+    } else {
+      FCoeff = dynamicFCoeff*(WheelSlip>=0?1.0:-1.0);
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Compute the vertical force on the wheel using square-law damping (per comment
+// in paper AIAA-2000-4303 - see header prologue comments). We might consider
+// allowing for both square and linear damping force calculation. Also need to
+// possibly give a "rebound damping factor" that differs from the compression
+// case.
+
+void FGLGear::ComputeVerticalStrutForce(void)
+{
+  double springForce = 0;
+  double dampForce = 0;
+
+  springForce = -compressLength * kSpring;
+
+  if (compressSpeed >= 0.0) {
+    dampForce   = -compressSpeed * bDamp;
+  } else {
+    dampForce   = -compressSpeed * bDampRebound;
+  }
+  vLocalForce(eZ) =  min(springForce + dampForce, (double)0.0);
+
+  // Remember these values for reporting
+  MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));
+  MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLGear::bind(void)
+{
+  char property_name[80];
+  snprintf(property_name, 80, "gear/unit[%d]/slip-angle-deg", GearNumber);
+  Exec->GetPropertyManager()->Tie( property_name, &WheelSlip );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLGear::unbind(void)
+{
+  char property_name[80];
+  snprintf(property_name, 80, "gear/unit[%d]/slip-angle-deg", GearNumber);
+  Exec->GetPropertyManager()->Untie( property_name );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGLGear::Report(ReportType repType)
+{
+  switch(repType) {
+  case erLand:
+    cout << endl << "Touchdown report for " << name << endl;
+    cout << "  Sink rate at contact:  " << SinkRate                << " fps,    "
+                                << SinkRate*0.3048          << " mps"     << endl;
+    cout << "  Contact ground speed:  " << GroundSpeed*.5925       << " knots,  "
+                                << GroundSpeed*0.3048       << " mps"     << endl;
+    cout << "  Maximum contact force: " << MaximumStrutForce       << " lbs,    "
+                                << MaximumStrutForce*4.448  << " Newtons" << endl;
+    cout << "  Maximum strut travel:  " << MaximumStrutTravel*12.0 << " inches, "
+                                << MaximumStrutTravel*30.48 << " cm"      << endl;
+    cout << "  Distance traveled:     " << LandingDistanceTraveled        << " ft,     "
+                                << LandingDistanceTraveled*0.3048  << " meters"  << endl;
+    LandingReported = true;
+    break;
+  case erTakeoff:
+    cout << endl << "Takeoff report for " << name << endl;
+    cout << "  Distance traveled:                " << TakeoffDistanceTraveled
+         << " ft,     " << TakeoffDistanceTraveled*0.3048  << " meters"  << endl;
+    cout << "  Distance traveled (over 50'):     " << TakeoffDistanceTraveled50ft
+         << " ft,     " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl;
+    TakeoffReported = true;
+    break;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGLGear::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor - loading and initialization
+      cout << "    " << sContactType << " " << name          << endl;
+      cout << "      Location: "         << vXYZ          << endl;
+      cout << "      Spring Constant:  " << kSpring       << endl;
+      cout << "      Damping Constant: " << bDamp         << endl;
+      cout << "      Dynamic Friction: " << dynamicFCoeff << endl;
+      cout << "      Static Friction:  " << staticFCoeff  << endl;
+      if (sContactType == "BOGEY") {
+        cout << "      Rolling Friction: " << rollingFCoeff << endl;
+        cout << "      Steering Type:    " << sSteerType    << endl;
+        cout << "      Grouping:         " << sBrakeGroup   << endl;
+        cout << "      Max Steer Angle:  " << maxSteerAngle << endl;
+        cout << "      Retractable:      " << isRetractable  << endl;
+      }
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGLGear" << endl;
+    if (from == 1) cout << "Destroyed:    FGLGear" << 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;
+    }
+  }
+}
+
+} // namespace JSBSim
+
diff --git a/src/FDM/JSBSim/models/FGLGear.h b/src/FDM/JSBSim/models/FGLGear.h
new file mode 100644 (file)
index 0000000..95b1d11
--- /dev/null
@@ -0,0 +1,347 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGLGear.h
+ Author:       Jon S. Berndt
+ Date started: 11/18/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/18/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGLGEAR_H
+#define FGLGEAR_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#endif
+
+#include <FGJSBBase.h>
+#include <FGFDMExec.h>
+#include <input_output/FGXMLElement.h>
+#include <math/FGColumnVector3.h>
+#include <math/FGTable.h>
+#include <string>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_LGEAR "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGAircraft;
+class FGPropagate;
+class FGFCS;
+class FGState;
+class FGMassBalance;
+class FGAuxiliary;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Landing gear model.
+    Calculates forces and moments due to landing gear reactions. This is done in
+    several steps, and is dependent on what kind of gear is being modeled. Here
+    are the parameters that can be specified in the config file for modeling
+    landing gear:
+    <p>
+    <b><u>Physical Characteristics</u></b><br>
+    <ol>
+    <li>X, Y, Z location, in inches in structural coordinate frame</li>
+    <li>Spring constant, in lbs/ft</li>
+    <li>Damping coefficient, in lbs/ft/sec</li>
+    <li>Dynamic Friction Coefficient</li>
+    <li>Static Friction Coefficient</li>
+    </ol></p><p>
+    <b><u>Operational Properties</b></u><br>
+    <ol>
+    <li>Name</li>
+    <li>Steerability attribute {one of STEERABLE | FIXED | CASTERED}</li>
+    <li>Brake Group Membership {one of LEFT | CENTER | RIGHT | NOSE | TAIL | NONE}</li>
+    <li>Max Steer Angle, in degrees</li>
+    </ol></p>
+    <p>
+    <b><u>Algorithm and Approach to Modeling</u></b><br>
+    <ol>
+    <li>Find the location of the uncompressed landing gear relative to the CG of
+    the aircraft. Remember, the structural coordinate frame that the aircraft is
+    defined in is: X positive towards the tail, Y positive out the right side, Z
+    positive upwards. The locations of the various parts are given in inches in
+    the config file.</li>
+    <li>The vector giving the location of the gear (relative to the cg) is
+    rotated 180 degrees about the Y axis to put the coordinates in body frame (X
+    positive forwards, Y positive out the right side, Z positive downwards, with
+    the origin at the cg). The lengths are also now given in feet.</li>
+    <li>The new gear location is now transformed to the local coordinate frame
+    using the body-to-local matrix. (Mb2l).</li>
+    <li>Knowing the location of the center of gravity relative to the ground
+    (height above ground level or AGL) now enables gear deflection to be
+    calculated. The gear compression value is the local frame gear Z location
+    value minus the height AGL. [Currently, we make the assumption that the gear
+    is oriented - and the deflection occurs in - the Z axis only. Additionally,
+    the vector to the landing gear is currently not modified - which would
+    (correctly) move the point of contact to the actual compressed-gear point of
+    contact. Eventually, articulated gear may be modeled, but initially an
+    effort must be made to model a generic system.] As an example, say the
+    aircraft left main gear location (in local coordinates) is Z = 3 feet
+    (positive) and the height AGL is 2 feet. This tells us that the gear is
+    compressed 1 foot.</li>
+    <li>If the gear is compressed, a Weight-On-Wheels (WOW) flag is set.</li>
+    <li>With the compression length calculated, the compression velocity may now
+    be calculated. This will be used to determine the damping force in the
+    strut. The aircraft rotational rate is multiplied by the vector to the wheel
+    to get a wheel velocity in body frame. That velocity vector is then
+    transformed into the local coordinate frame.</li>
+    <li>The aircraft cg velocity in the local frame is added to the
+    just-calculated wheel velocity (due to rotation) to get a total wheel
+    velocity in the local frame.</li>
+    <li>The compression speed is the Z-component of the vector.</li>
+    <li>With the wheel velocity vector no longer needed, it is normalized and
+    multiplied by a -1 to reverse it. This will be used in the friction force
+    calculation.</li>
+    <li>Since the friction force takes place solely in the runway plane, the Z
+    coordinate of the normalized wheel velocity vector is set to zero.</li>
+    <li>The gear deflection force (the force on the aircraft acting along the
+    local frame Z axis) is now calculated given the spring and damper
+    coefficients, and the gear deflection speed and stroke length. Keep in mind
+    that gear forces always act in the negative direction (in both local and
+    body frames), and are not capable of generating a force in the positive
+    sense (one that would attract the aircraft to the ground). So, the gear
+    forces are always negative - they are limited to values of zero or less. The
+    gear force is simply the negative of the sum of the spring compression
+    length times the spring coefficient and the gear velocity times the damping
+    coefficient.</li>
+    <li>The lateral/directional force acting on the aircraft through the landing
+
+    gear (along the local frame X and Y axes) is calculated next. First, the
+    friction coefficient is multiplied by the recently calculated Z-force. This
+    is the friction force. It must be given direction in addition to magnitude.
+    We want the components in the local frame X and Y axes. From step 9, above,
+    the conditioned wheel velocity vector is taken and the X and Y parts are
+    multiplied by the friction force to get the X and Y components of friction.
+    </li>
+    <li>The wheel force in local frame is next converted to body frame.</li>
+    <li>The moment due to the gear force is calculated by multiplying r x F
+    (radius to wheel crossed into the wheel force). Both of these operands are
+    in body frame.</li>
+    </ol>
+    @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
+    @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
+     Wiley & Sons, 1979 ISBN 0-471-03032-5
+    @see W. A. Ragsdale, "A Generic Landing Gear Dynamics Model for LASRS++",
+     AIAA-2000-4303
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGLGear : public FGJSBBase
+{
+public:
+  /// Brake grouping enumerators
+  enum BrakeGroup {bgNone=0, bgLeft, bgRight, bgCenter, bgNose, bgTail };
+  /// Steering group membership enumerators
+  enum SteerType {stSteer, stFixed, stCaster};
+  /// Report type enumerators
+  enum ReportType {erNone=0, erTakeoff, erLand};
+  /** Constructor
+      @param el a pointer to the XML element that contains the CONTACT info.
+      @param Executive a pointer to the parent executive object
+      @param File a pointer to the config file instance */
+  FGLGear(Element* el, FGFDMExec* Executive, int number);
+  /** Constructor
+      @param lgear a reference to an existing FGLGear object     */
+  FGLGear(const FGLGear& lgear);
+  /// Destructor
+  ~FGLGear();
+
+
+  /// The Force vector for this gear
+  FGColumnVector3& Force(void);
+  /// The Moment vector for this gear
+  FGColumnVector3& Moment(void) {return vMoment;}
+
+  /// Gets the location of the gear in Body axes
+  FGColumnVector3& GetBodyLocation(void) { return vWhlBodyVec; }
+  double GetBodyLocation(int idx) { return vWhlBodyVec(idx); }
+
+  FGColumnVector3& GetLocalGear(void) { return vLocalGear; }
+  double GetLocalGear(int idx) { return vLocalGear(idx); }
+
+  /// Gets the name of the gear
+  inline string GetName(void)      {return name;          }
+  /// Gets the Weight On Wheels flag value
+  inline bool   GetWOW(void)       {return WOW;           }
+  /// Gets the current compressed length of the gear in feet
+  inline double  GetCompLen(void)   {return compressLength;}
+  /// Gets the current gear compression velocity in ft/sec
+  inline double  GetCompVel(void)   {return compressSpeed; }
+  /// Gets the gear compression force in pounds
+  inline double  GetCompForce(void) {return Force()(3);    }
+  inline double  GetBrakeFCoeff(void) {return BrakeFCoeff;}
+
+  /// Gets the current normalized tire pressure
+  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;}
+
+  /** Set the console touchdown reporting feature
+      @param flag true turns on touchdown reporting, false turns it off */
+  inline void SetReport(bool flag) { ReportEnable = flag; }
+  /** Get the console touchdown reporting feature
+      @return true if reporting is turned on */
+  inline bool GetReport(void)    { return ReportEnable; }
+  double GetSteerNorm(void) const { return radtodeg/maxSteerAngle*SteerAngle; }
+  double GetDefaultSteerAngle(double cmd) const { return cmd*maxSteerAngle; }
+  double GetstaticFCoeff(void) { return staticFCoeff; }
+
+  inline int GetBrakeGroup(void) { return (int)eBrakeGrp; }
+  inline int GetSteerType(void)  { return (int)eSteerType; }
+
+  bool GetSteerable(void) const { return eSteerType != stFixed; }
+  inline bool GetRetractable(void)         { return isRetractable;   }
+  inline bool GetGearUnitUp(void)          { return GearUp;          }
+  inline bool GetGearUnitDown(void)        { return GearDown;        }
+  inline double GetWheelSideForce(void)    { return SideForce;       }
+  inline double GetWheelRollForce(void)    { return RollingForce;    }
+  inline double GetBodyXForce(void)        { return vLocalForce(eX); }
+  inline double GetBodyYForce(void)        { return vLocalForce(eY); }
+  inline double GetWheelSlipAngle(void)    { return WheelSlip;       }
+  double GetWheelVel(int axis)             { return vWhlVelVec(axis);}
+
+  bool IsBogey(void) {return (sContactType == string("BOGEY"));}
+
+  void bind(void);
+  void unbind(void);
+
+private:
+  int GearNumber;
+  FGColumnVector3 vXYZ;
+  FGColumnVector3 vMoment;
+  FGColumnVector3 vWhlBodyVec;
+  FGColumnVector3 vLocalGear;
+  FGColumnVector3 vForce;
+  FGColumnVector3 last_vForce; // remove this
+  FGColumnVector3 vLocalForce;
+  FGColumnVector3 vWhlVelVec;     // Velocity of this wheel (Local)
+  FGColumnVector3 In;
+  FGColumnVector3 prevIn;
+  FGColumnVector3 prevOut;
+  FGTable *ForceY_Table;
+  double SteerAngle;
+  double kSpring;
+  double bDamp;
+  double bDampRebound;
+  double compressLength;
+  double compressSpeed;
+  double staticFCoeff, dynamicFCoeff, rollingFCoeff;
+  double brakePct;
+  double BrakeFCoeff;
+  double maxCompLen;
+  double SinkRate;
+  double GroundSpeed;
+  double TakeoffDistanceTraveled;
+  double TakeoffDistanceTraveled50ft;
+  double LandingDistanceTraveled;
+  double MaximumStrutForce;
+  double MaximumStrutTravel;
+  double SideWhlVel, RollingWhlVel;
+  double RollingForce, SideForce, FCoeff;
+  double WheelSlip;
+  double last_WheelSlip;
+  double slipIn;
+  double last_SlipIn;
+  double TirePressureNorm;
+  double SinWheel, CosWheel;
+  bool WOW;
+  bool lastWOW;
+  bool FirstContact;
+  bool StartedGroundRun;
+  bool LandingReported;
+  bool TakeoffReported;
+  bool ReportEnable;
+  bool isRetractable;
+  bool GearUp, GearDown;
+  bool Servicable;
+  string name;
+  string sSteerType;
+  string sBrakeGroup;
+  string sRetractable;
+  string sContactType;
+
+  BrakeGroup eBrakeGrp;
+  SteerType  eSteerType;
+  double  maxSteerAngle;
+
+  FGFDMExec*     Exec;
+  FGState*       State;
+  FGAircraft*    Aircraft;
+  FGPropagate*   Propagate;
+  FGAuxiliary*   Auxiliary;
+  FGFCS*         FCS;
+  FGMassBalance* MassBalance;
+
+  void ComputeRetractionState(void);
+  void ComputeBrakeForceCoefficient(void);
+  void ComputeSteeringAngle(void);
+  void ComputeSlipAngle(void);
+  void ComputeSideForceCoefficient(void);
+  void ComputeVerticalStrutForce(void);
+  void CrashDetect(void);
+  void InitializeReporting(void);
+  void ResetReporting(void);
+  void ReportTakeoffOrLanding(void);
+  void Report(ReportType rt);
+  void Debug(int from);
+};
+}
+#include "FGAircraft.h"
+#include "FGPropagate.h"
+#include "FGAuxiliary.h"
+#include "FGFCS.h"
+#include "FGMassBalance.h"
+#include "FGState.h"
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif
diff --git a/src/FDM/JSBSim/models/FGMassBalance.cpp b/src/FDM/JSBSim/models/FGMassBalance.cpp
new file mode 100644 (file)
index 0000000..73892ba
--- /dev/null
@@ -0,0 +1,377 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGMassBalance.cpp
+ Author:       Jon S. Berndt
+ Date started: 09/12/2000
+ Purpose:      This module models weight and balance
+
+ ------------- Copyright (C) 2000  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 models the change in weight and balance of the aircraft due to fuel
+burnoff, etc.
+
+HISTORY
+--------------------------------------------------------------------------------
+09/12/2000  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGMassBalance.h"
+#include "FGPropulsion.h"
+#include <input_output/FGPropertyManager.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_MASSBALANCE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGMassBalance::FGMassBalance(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGMassBalance";
+  Weight = EmptyWeight = Mass = 0.0;
+
+  vbaseXYZcg.InitMatrix(0.0);
+  baseJ.InitMatrix();
+  mJ.InitMatrix();
+  mJinv.InitMatrix();
+  pmJ.InitMatrix();
+
+  bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMassBalance::~FGMassBalance()
+{
+  unbind();
+  PointMasses.clear();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGMassBalance::Load(Element* el)
+{
+  Element *element;
+  string element_name = "";
+  double bixx, biyy, bizz, bixy, bixz, biyz;
+
+  bixx = biyy = bizz = bixy = bixz = biyz = 0.0;
+  if (el->FindElement("ixx"))
+    bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
+  if (el->FindElement("iyy"))
+    biyy = el->FindElementValueAsNumberConvertTo("iyy", "SLUG*FT2");
+  if (el->FindElement("izz"))
+    bizz = el->FindElementValueAsNumberConvertTo("izz", "SLUG*FT2");
+  if (el->FindElement("ixy"))
+    bixy = el->FindElementValueAsNumberConvertTo("ixy", "SLUG*FT2");
+  if (el->FindElement("ixz"))
+    bixz = el->FindElementValueAsNumberConvertTo("ixz", "SLUG*FT2");
+  if (el->FindElement("iyz"))
+    biyz = el->FindElementValueAsNumberConvertTo("iyz", "SLUG*FT2");
+  SetAircraftBaseInertias(FGMatrix33(  bixx,  -bixy,  -bixz,
+                                      -bixy,  biyy,  -biyz,
+                                      -bixz,  -biyz,  bizz ));
+  EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS");
+
+  element = el->FindElement("location");
+   while (element) {
+     element_name = element->GetAttributeValue("name");
+     if (element_name == "CG") vbaseXYZcg = element->FindElementTripletConvertTo("IN");
+     element = el->FindNextElement("location");
+   }
+
+// Find all POINTMASS elements that descend from this METRICS branch of the
+// config file.
+
+  element = el->FindElement("pointmass");
+  while (element) {
+    AddPointMass(element);
+    element = el->FindNextElement("pointmass");
+  }
+
+  Debug(2);
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGMassBalance::Run(void)
+{
+  double denom, k1, k2, k3, k4, k5, k6;
+  double Ixx, Iyy, Izz, Ixy, Ixz, Iyz;
+
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetPointMassWeight();
+
+  Mass = lbtoslug*Weight;
+
+// Calculate new CG
+
+//  printf("%s:%i\n", __FILE__, __LINE__);
+  vXYZcg = (Propulsion->GetTanksMoment() + EmptyWeight*vbaseXYZcg
+                                     + GetPointMassMoment() ) / Weight;
+
+// Calculate new total moments of inertia
+
+  // At first it is the base configuration inertia matrix ...
+  mJ = baseJ;
+  // ... with the additional term originating from the parallel axis theorem.
+  mJ += GetPointmassInertia( lbtoslug * EmptyWeight, vbaseXYZcg );
+  // Then add the contributions from the additional pointmasses.
+  mJ += CalculatePMInertias();
+  mJ += Propulsion->CalculateTankInertias();
+
+  Ixx = mJ(1,1);
+  Iyy = mJ(2,2);
+  Izz = mJ(3,3);
+  Ixy = -mJ(1,2);
+  Ixz = -mJ(1,3);
+  Iyz = -mJ(2,3);
+
+// Calculate inertia matrix inverse (ref. Stevens and Lewis, "Flight Control & Simulation")
+
+  k1 = (Iyy*Izz - Iyz*Iyz);
+  k2 = (Iyz*Ixz + Ixy*Izz);
+  k3 = (Ixy*Iyz + Iyy*Ixz);
+
+  denom = 1.0/(Ixx*k1 - Ixy*k2 - Ixz*k3 );
+  k1 = k1*denom;
+  k2 = k2*denom;
+  k3 = k3*denom;
+  k4 = (Izz*Ixx - Ixz*Ixz)*denom;
+  k5 = (Ixy*Ixz + Iyz*Ixx)*denom;
+  k6 = (Ixx*Iyy - Ixy*Ixy)*denom;
+
+  mJinv.InitMatrix( k1, k2, k3,
+                    k2, k4, k5,
+                    k3, k5, k6 );
+
+  Debug(0);
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMassBalance::AddPointMass(Element* el)
+{
+  Element* loc_element = el->FindElement("location");
+  string pointmass_name = el->GetAttributeValue("name");
+  if (!el) {
+    cerr << "Pointmass " << pointmass_name << "has no location." << endl;
+    exit(-1);
+  }
+  string loc_unit = loc_element->GetAttributeValue("unit");
+  double w, x, y, z;
+
+  w = el->FindElementValueAsNumberConvertTo("weight", "LBS");
+  x = loc_element->FindElementValueAsNumberConvertTo("x", loc_unit);
+  y = loc_element->FindElementValueAsNumberConvertTo("y", loc_unit);
+  z = loc_element->FindElementValueAsNumberConvertTo("z", loc_unit);
+
+  PointMasses.push_back(PointMass(w, x, y, z));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGMassBalance::GetPointMassWeight(void)
+{
+  double PM_total_weight = 0.0;
+
+  for (unsigned int i=0; i<PointMasses.size(); i++) {
+    PM_total_weight += PointMasses[i].Weight;
+  }
+  return PM_total_weight;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGMassBalance::GetPointMassMoment(void)
+{
+  PointMassCG.InitMatrix();
+
+  for (unsigned int i=0; i<PointMasses.size(); i++) {
+    PointMassCG += PointMasses[i].Weight*PointMasses[i].Location;
+  }
+  return PointMassCG;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33& FGMassBalance::CalculatePMInertias(void)
+{
+  unsigned int size;
+
+  size = PointMasses.size();
+  if (size == 0) return pmJ;
+
+  pmJ = FGMatrix33();
+
+  for (unsigned int i=0; i<size; i++)
+    pmJ += GetPointmassInertia( lbtoslug * PointMasses[i].Weight, PointMasses[i].Location );
+
+  return pmJ;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3 FGMassBalance::StructuralToBody(const FGColumnVector3& r) const
+{
+  // Under the assumption that in the structural frame the:
+  //
+  // - X-axis is directed afterwards,
+  // - Y-axis is directed towards the right,
+  // - Z-axis is directed upwards,
+  //
+  // (as documented in http://jsbsim.sourceforge.net/JSBSimCoordinates.pdf)
+  // we have to subtract first the center of gravity of the plane which
+  // is also defined in the structural frame:
+  //
+  //   FGColumnVector3 cgOff = r - vXYZcg;
+  //
+  // Next, we do a change of units:
+  //
+  //   cgOff *= inchtoft;
+  //
+  // And then a 180 degree rotation is done about the Y axis so that the:
+  //
+  // - X-axis is directed forward,
+  // - Y-axis is directed towards the right,
+  // - Z-axis is directed downward.
+  //
+  // This is needed because the structural and body frames are 180 degrees apart.
+
+  return FGColumnVector3(inchtoft*(vXYZcg(1)-r(1)),
+                         inchtoft*(r(2)-vXYZcg(2)),
+                         inchtoft*(vXYZcg(3)-r(3)));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMassBalance::bind(void)
+{
+  typedef double (FGMassBalance::*PMF)(int) const;
+  PropertyManager->Tie("inertia/mass-slugs", this,
+                       &FGMassBalance::GetMass);
+  PropertyManager->Tie("inertia/weight-lbs", this,
+                       &FGMassBalance::GetWeight);
+  PropertyManager->Tie("inertia/cg-x-ft", this,1,
+                       (PMF)&FGMassBalance::GetXYZcg);
+  PropertyManager->Tie("inertia/cg-y-ft", this,2,
+                       (PMF)&FGMassBalance::GetXYZcg);
+  PropertyManager->Tie("inertia/cg-z-ft", this,3,
+                       (PMF)&FGMassBalance::GetXYZcg);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMassBalance::unbind(void)
+{
+  PropertyManager->Untie("inertia/mass-slugs");
+  PropertyManager->Untie("inertia/weight-lbs");
+  PropertyManager->Untie("inertia/cg-x-ft");
+  PropertyManager->Untie("inertia/cg-y-ft");
+  PropertyManager->Untie("inertia/cg-z-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 FGMassBalance::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 2) { // Loading
+      cout << endl << "  Mass and Balance:" << endl;
+      cout << "    baseIxx: " << baseJ(1,1) << " slug-ft2" << endl;
+      cout << "    baseIyy: " << baseJ(2,2) << " slug-ft2" << endl;
+      cout << "    baseIzz: " << baseJ(3,3) << " slug-ft2" << endl;
+      cout << "    baseIxy: " << baseJ(1,2) << " slug-ft2" << endl;
+      cout << "    baseIxz: " << baseJ(1,3) << " slug-ft2" << endl;
+      cout << "    baseIyz: " << baseJ(2,3) << " slug-ft2" << endl;
+      cout << "    EmptyWeight: " << EmptyWeight << " lbm" << endl;
+      cout << "    CG (x, y, z): " << vbaseXYZcg << endl;
+      // ToDo: Need to add point mass outputs here
+      for (int i=0; i<PointMasses.size(); i++) {
+        cout << "    Point Mass Object: " << PointMasses[i].Weight << " lbs. at "
+                   << "X, Y, Z (in.): " << PointMasses[i].Location(eX) << "  "
+                   << PointMasses[i].Location(eY) << "  "
+                   << PointMasses[i].Location(eZ) << endl;
+      }
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGMassBalance" << endl;
+    if (from == 1) cout << "Destroyed:    FGMassBalance" << 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 (from == 2) {
+      if (EmptyWeight <= 0.0 || EmptyWeight > 1e9)
+        cout << "MassBalance::EmptyWeight out of bounds: " << EmptyWeight << endl;
+      if (Weight <= 0.0 || Weight > 1e9)
+        cout << "MassBalance::Weight out of bounds: " << Weight << endl;
+      if (Mass <= 0.0 || Mass > 1e9)
+        cout << "MassBalance::Mass out of bounds: " << Mass << endl;
+    }
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+}
diff --git a/src/FDM/JSBSim/models/FGMassBalance.h b/src/FDM/JSBSim/models/FGMassBalance.h
new file mode 100644 (file)
index 0000000..e1cfb48
--- /dev/null
@@ -0,0 +1,163 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGMassBalance.h
+ Author:       Jon S. Berndt
+ Date started: 09/12/2000
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+09/12/2000  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGMASSBALANCE_H
+#define FGMASSBALANCE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGModel.h"
+#include <math/FGColumnVector3.h>
+#include <math/FGMatrix33.h>
+#include <input_output/FGXMLElement.h>
+#include <vector>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_MASSBALANCE "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONSS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models weight and balance information.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGMassBalance : public FGModel
+{
+
+public:
+  FGMassBalance(FGFDMExec*);
+  ~FGMassBalance();
+
+  bool Load(Element* el);
+
+  bool Run(void);
+
+  inline double GetMass(void) const {return Mass;}
+  inline double GetWeight(void) const {return Weight;}
+  inline FGColumnVector3& GetXYZcg(void) {return vXYZcg;}
+  inline double GetXYZcg(int axis) const  {return vXYZcg(axis);}
+
+  /** Computes the inertia contribution of a pointmass.
+      Computes and returns the inertia matrix of a pointmass of mass
+      slugs at the given vector r in the structural frame. The units
+      should be for the mass in slug and the vector in the structural
+      frame as usual in inches.
+      @param slugs the mass of this single pointmass given in slugs
+      @param r the location of this single pointmass in the structural frame
+   */
+  FGMatrix33 GetPointmassInertia(double slugs, const FGColumnVector3& r) const
+  {
+    FGColumnVector3 v = StructuralToBody( r );
+    FGColumnVector3 sv = slugs*v;
+    double xx = sv(1)*v(1);
+    double yy = sv(2)*v(2);
+    double zz = sv(3)*v(3);
+    double xy = -sv(1)*v(2);
+    double xz = -sv(1)*v(3);
+    double yz = -sv(2)*v(3);
+    return FGMatrix33( yy+zz, xy, xz,
+                       xy, xx+zz, yz,
+                       xz, yz, xx+yy );
+  }
+
+  /** Conversion from the structural frame to the body frame.
+      Converts the location given in the structural frame
+      coordinate system to the body frame. The units of the structural
+      frame are assumed to be in inches. The unit of the result is in
+      ft.
+      @param r vector coordinate in the structural reference frame (X positive
+               aft, measurements in inches).
+      @return vector coordinate in the body frame, in feet.
+   */
+  FGColumnVector3 StructuralToBody(const FGColumnVector3& r) const;
+
+  inline void SetEmptyWeight(double EW) { EmptyWeight = EW;}
+  inline void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = vXYZcg = CG;}
+
+  void AddPointMass(Element* el);
+  double GetPointMassWeight(void);
+  FGColumnVector3& GetPointMassMoment(void);
+  FGMatrix33& GetJ(void) {return mJ;}
+  FGMatrix33& GetJinv(void) {return mJinv;}
+  void SetAircraftBaseInertias(FGMatrix33 BaseJ) {baseJ = BaseJ;}
+
+  void bind(void);
+  void unbind(void);
+
+private:
+  double Weight;
+  double EmptyWeight;
+  double Mass;
+  FGMatrix33 mJ;
+  FGMatrix33 mJinv;
+  FGMatrix33 pmJ;
+  FGMatrix33 baseJ;
+  FGColumnVector3 vXYZcg;
+  FGColumnVector3 vXYZtank;
+  FGColumnVector3 vbaseXYZcg;
+  FGColumnVector3 vPMxyz;
+  FGColumnVector3 PointMassCG;
+  FGMatrix33& CalculatePMInertias(void);
+
+  struct PointMass {
+    PointMass(double w, double x, double y, double z) {
+      Weight = w;
+      Location.InitMatrix(x, y, z);
+    }
+    FGColumnVector3 Location;
+    double Weight;
+  };
+
+  vector <struct PointMass> PointMasses;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/models/FGModel.cpp b/src/FDM/JSBSim/models/FGModel.cpp
new file mode 100644 (file)
index 0000000..53f2500
--- /dev/null
@@ -0,0 +1,193 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGModel.cpp
+ Author:       Jon Berndt
+ Date started: 11/11/98
+ Purpose:      Base class for all models
+ Called by:    FGSimExec, 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 base class for the FGAerodynamics, FGPropagate, etc. classes defines methods
+common to all models.
+
+HISTORY
+--------------------------------------------------------------------------------
+11/11/98   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGModel.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+#include "FGAtmosphere.h"
+#include "FGFCS.h"
+#include "FGPropulsion.h"
+#include "FGMassBalance.h"
+#include "FGAerodynamics.h"
+#include "FGInertial.h"
+#include "FGGroundReactions.h"
+#include "FGAircraft.h"
+#include "FGPropagate.h"
+#include "FGAuxiliary.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_MODEL;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+GLOBAL DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGModel::FGModel(FGFDMExec* fdmex)
+{
+  FDMExec     = fdmex;
+  NextModel   = 0L;
+
+  State           = 0;
+  Atmosphere      = 0;
+  FCS             = 0;
+  Propulsion      = 0;
+  MassBalance     = 0;
+  Aerodynamics    = 0;
+  Inertial        = 0;
+  GroundReactions = 0;
+  Aircraft        = 0;
+  Propagate       = 0;
+  Auxiliary       = 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;
+
+  if (debug_lvl & 2) cout << "              FGModel Base Class" << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGModel::~FGModel()
+{
+  if (debug_lvl & 2) cout << "Destroyed:    FGModel" << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGModel::InitModel(void)
+{
+  State           = FDMExec->GetState();
+  Atmosphere      = FDMExec->GetAtmosphere();
+  FCS             = FDMExec->GetFCS();
+  Propulsion      = FDMExec->GetPropulsion();
+  MassBalance     = FDMExec->GetMassBalance();
+  Aerodynamics    = FDMExec->GetAerodynamics();
+  Inertial        = FDMExec->GetInertial();
+  GroundReactions = FDMExec->GetGroundReactions();
+  Aircraft        = FDMExec->GetAircraft();
+  Propagate       = FDMExec->GetPropagate();
+  Auxiliary       = FDMExec->GetAuxiliary();
+
+  if (!State ||
+      !Atmosphere ||
+      !FCS ||
+      !Propulsion ||
+      !MassBalance ||
+      !Aerodynamics ||
+      !Inertial ||
+      !GroundReactions ||
+      !Aircraft ||
+      !Propagate ||
+      !Auxiliary) return(false);
+  else return(true);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGModel::Run()
+{
+  if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl;
+
+  if (exe_ctr == 1) {
+    if (exe_ctr++ >= rate) exe_ctr = 1;
+    return false;
+  } else {
+    if (exe_ctr++ >= rate) exe_ctr = 1;
+    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 FGModel::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: FGModel" << endl;
+    if (from == 1) cout << "Destroyed:    FGModel" << 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/models/FGModel.h b/src/FDM/JSBSim/models/FGModel.h
new file mode 100644 (file)
index 0000000..d1907e3
--- /dev/null
@@ -0,0 +1,151 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGModel.h
+ Author:       Jon Berndt
+ Date started: 11/21/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
+--------------------------------------------------------------------------------
+11/22/98   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGMODEL_H
+#define FGMODEL_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <FGJSBBase.h>
+#include <input_output/FGPropertyManager.h>
+#include <input_output/FGXMLElement.h>
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <iostream>
+#  else
+#    include <iostream.h>
+#  endif
+#else
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <iostream.h>
+#  else
+#    include <iostream>
+#  endif
+#endif
+
+#include <string>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_MODEL "$Id$"
+
+using namespace std;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFDMExec;
+class FGState;
+class FGAtmosphere;
+class FGFCS;
+class FGPropulsion;
+class FGMassBalance;
+class FGAerodynamics;
+class FGInertial;
+class FGGroundReactions;
+class FGAircraft;
+class FGPropagate;
+class FGAuxiliary;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Base class for all scheduled JSBSim models
+    @author Jon S. Berndt
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGModel : public FGJSBBase
+{
+public:
+
+  /// Constructor
+  FGModel(FGFDMExec*);
+  /// Destructor
+  virtual ~FGModel();
+
+  /** Loads this model.
+      @param el a pointer to the element
+      @return true if model is successfully loaded*/
+  virtual bool Load(Element* el) {return true;}
+
+  FGModel* NextModel;
+  string Name;
+
+  /** Runs the model; called by the Executive
+      @see JSBSim.cpp documentation
+      @return false if no error */
+  virtual bool Run(void);
+  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;
+  FGState*           State;
+  FGAtmosphere*      Atmosphere;
+  FGFCS*             FCS;
+  FGPropulsion*      Propulsion;
+  FGMassBalance*     MassBalance;
+  FGAerodynamics*    Aerodynamics;
+  FGInertial*        Inertial;
+  FGGroundReactions* GroundReactions;
+  FGAircraft*        Aircraft;
+  FGPropagate*       Propagate;
+  FGAuxiliary*       Auxiliary;
+  FGPropertyManager* PropertyManager;
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGOutput.cpp b/src/FDM/JSBSim/models/FGOutput.cpp
new file mode 100644 (file)
index 0000000..4f1e669
--- /dev/null
@@ -0,0 +1,740 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGOutput.cpp
+ Author:       Jon Berndt
+ Date started: 12/02/98
+ Purpose:      Manage output of sim parameters to file or stdout
+ 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
+ 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 is the place where you create output routines to dump data for perusal
+later.
+
+HISTORY
+--------------------------------------------------------------------------------
+12/02/98   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGOutput.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+#include "FGAtmosphere.h"
+#include "FGFCS.h"
+#include "FGAerodynamics.h"
+#include "FGGroundReactions.h"
+#include "FGAircraft.h"
+#include "FGMassBalance.h"
+#include "FGPropagate.h"
+#include "FGAuxiliary.h"
+#include "FGInertial.h"
+
+#include <fstream>
+#include <iomanip>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_OUTPUT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGOutput";
+  sFirstPass = dFirstPass = true;
+  socket = 0;
+  Type = otNone;
+  SubSystems = 0;
+  enabled = true;
+  delimeter = ", ";
+  Filename = "";
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGOutput::~FGOutput()
+{
+  if (socket) delete socket;
+  OutputProperties.clear();
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGOutput::Run(void)
+{
+  if (FGModel::Run()) return true;
+
+  if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) {
+    if (Type == otSocket) {
+      SocketOutput();
+    } else if (Type == otCSV || Type == otTab) {
+      DelimitedOutput(Filename);
+    } else if (Type == otTerminal) {
+      // Not done yet
+    } else if (Type == otNone) {
+      // Do nothing
+    } else {
+      // Not a valid type of output
+    }
+  }
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGOutput::SetType(string type)
+{
+  if (type == "CSV") {
+    Type = otCSV;
+    delimeter = ", ";
+  } else if (type == "TABULAR") {
+    Type = otTab;
+    delimeter = "\t";
+  } else if (type == "SOCKET") {
+    Type = otSocket;
+  } else if (type == "TERMINAL") {
+    Type = otTerminal;
+  } else if (type != string("NONE")) {
+    Type = otUnknown;
+    cerr << "Unknown type of output specified in config file" << endl;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGOutput::DelimitedOutput(string fname)
+{
+  streambuf* buffer;
+  string scratch = "";
+
+  if (fname == "COUT" || fname == "cout") {
+    buffer = cout.rdbuf();
+  } else {
+    datafile.open(fname.c_str());
+    buffer = datafile.rdbuf();
+  }
+
+  ostream outstream(buffer);
+
+  if (dFirstPass) {
+    outstream << "Time";
+    if (SubSystems & ssSimulation) {
+      // Nothing here, yet
+    }
+    if (SubSystems & ssAerosurfaces) {
+      outstream << delimeter;
+      outstream << "Aileron Cmd" + delimeter;
+      outstream << "Elevator Cmd" + delimeter;
+      outstream << "Rudder Cmd" + delimeter;
+      outstream << "Flap Cmd" + delimeter;
+      outstream << "Left Aileron Pos" + delimeter;
+      outstream << "Right Aileron Pos" + delimeter;
+      outstream << "Elevator Pos" + delimeter;
+      outstream << "Rudder Pos" + delimeter;
+      outstream << "Flap Pos";
+    }
+    if (SubSystems & ssRates) {
+      outstream << delimeter;
+      outstream << "P" + delimeter + "Q" + delimeter + "R" + delimeter;
+      outstream << "Pdot" + delimeter + "Qdot" + delimeter + "Rdot";
+    }
+    if (SubSystems & ssVelocities) {
+      outstream << delimeter;
+      outstream << "QBar" + delimeter;
+      outstream << "Vtotal" + delimeter;
+      outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
+      outstream << "UAero" + delimeter + "VAero" + delimeter + "WAero" + delimeter;
+      outstream << "Vn" + delimeter + "Ve" + delimeter + "Vd";
+    }
+    if (SubSystems & ssForces) {
+      outstream << delimeter;
+      outstream << "Drag" + delimeter + "Side" + delimeter + "Lift" + delimeter;
+      outstream << "L/D" + delimeter;
+      outstream << "Xforce" + delimeter + "Yforce" + delimeter + "Zforce";
+    }
+    if (SubSystems & ssMoments) {
+      outstream << delimeter;
+      outstream << "L" + delimeter + "M" + delimeter + "N";
+    }
+    if (SubSystems & ssAtmosphere) {
+      outstream << delimeter;
+      outstream << "Rho" + delimeter;
+      outstream << "SL pressure" + delimeter;
+      outstream << "Ambient pressure" + delimeter;
+      outstream << "NWind" + delimeter + "EWind" + delimeter + "DWind";
+    }
+    if (SubSystems & ssMassProps) {
+      outstream << delimeter;
+      outstream << "Ixx" + delimeter;
+      outstream << "Ixy" + delimeter;
+      outstream << "Ixz" + delimeter;
+      outstream << "Iyx" + delimeter;
+      outstream << "Iyy" + delimeter;
+      outstream << "Iyz" + delimeter;
+      outstream << "Izx" + delimeter;
+      outstream << "Izy" + delimeter;
+      outstream << "Izz" + delimeter;
+      outstream << "Mass" + delimeter;
+      outstream << "Xcg" + delimeter + "Ycg" + delimeter + "Zcg";
+    }
+    if (SubSystems & ssPropagate) {
+      outstream << delimeter;
+      outstream << "Altitude" + delimeter;
+      outstream << "Phi" + delimeter + "Tht" + delimeter + "Psi" + delimeter;
+      outstream << "Alpha" + delimeter;
+      outstream << "Beta" + delimeter;
+      outstream << "Latitude (Deg)" + delimeter;
+      outstream << "Longitude (Deg)" + delimeter;
+      outstream << "Distance AGL" + delimeter;
+      outstream << "Runway Radius";
+    }
+    if (SubSystems & ssCoefficients) {
+      scratch = Aerodynamics->GetCoefficientStrings(delimeter);
+      if (scratch.length() != 0) outstream << delimeter << scratch;
+    }
+    if (SubSystems & ssFCS) {
+      scratch = FCS->GetComponentStrings(delimeter);
+      if (scratch.length() != 0) outstream << delimeter << scratch;
+    }
+    if (SubSystems & ssGroundReactions) {
+      outstream << delimeter;
+      outstream << GroundReactions->GetGroundReactionStrings(delimeter);
+    }
+    if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
+      outstream << delimeter;
+      outstream << Propulsion->GetPropulsionStrings(delimeter);
+    }
+    if (OutputProperties.size() > 0) {
+      for (unsigned int i=0;i<OutputProperties.size();i++) {
+        outstream << delimeter << OutputProperties[i]->GetName();
+      }
+    }
+
+    outstream << endl;
+    dFirstPass = false;
+  }
+
+  outstream << State->Getsim_time();
+  if (SubSystems & ssSimulation) {
+  }
+  if (SubSystems & ssAerosurfaces) {
+    outstream << delimeter;
+    outstream << FCS->GetDaCmd() << delimeter;
+    outstream << FCS->GetDeCmd() << delimeter;
+    outstream << FCS->GetDrCmd() << delimeter;
+    outstream << FCS->GetDfCmd() << delimeter;
+    outstream << FCS->GetDaLPos() << delimeter;
+    outstream << FCS->GetDaRPos() << delimeter;
+    outstream << FCS->GetDePos() << delimeter;
+    outstream << FCS->GetDrPos() << delimeter;
+    outstream << FCS->GetDfPos();
+  }
+  if (SubSystems & ssRates) {
+    outstream << delimeter;
+    outstream << Propagate->GetPQR().Dump(delimeter) << delimeter;
+    outstream << Propagate->GetPQRdot().Dump(delimeter);
+  }
+  if (SubSystems & ssVelocities) {
+    outstream << delimeter;
+    outstream << Auxiliary->Getqbar() << delimeter;
+    outstream << setprecision(12) << Auxiliary->GetVt() << delimeter;
+    outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
+    outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
+    outstream << Propagate->GetVel().Dump(delimeter);
+  }
+  if (SubSystems & ssForces) {
+    outstream << delimeter;
+    outstream << Aerodynamics->GetvFs() << delimeter;
+    outstream << Aerodynamics->GetLoD() << delimeter;
+    outstream << Aircraft->GetForces().Dump(delimeter);
+  }
+  if (SubSystems & ssMoments) {
+    outstream << delimeter;
+    outstream << Aircraft->GetMoments().Dump(delimeter);
+  }
+  if (SubSystems & ssAtmosphere) {
+    outstream << delimeter;
+    outstream << Atmosphere->GetDensity() << delimeter;
+    outstream << Atmosphere->GetPressureSL() << delimeter;
+    outstream << Atmosphere->GetPressure() << delimeter;
+    outstream << Atmosphere->GetWindNED().Dump(delimeter);
+  }
+  if (SubSystems & ssMassProps) {
+    outstream << delimeter;
+    outstream << MassBalance->GetJ() << delimeter;
+    outstream << MassBalance->GetMass() << delimeter;
+    outstream << MassBalance->GetXYZcg();
+  }
+  if (SubSystems & ssPropagate) {
+    outstream << delimeter;
+    outstream << Propagate->Geth() << delimeter;
+    outstream << Propagate->GetEuler().Dump(delimeter) << delimeter;
+    outstream << Auxiliary->Getalpha(inDegrees) << delimeter;
+    outstream << Auxiliary->Getbeta(inDegrees) << delimeter;
+    outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter;
+    outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter;
+    outstream << Propagate->GetDistanceAGL() << delimeter;
+    outstream << Propagate->GetRunwayRadius();
+  }
+  if (SubSystems & ssCoefficients) {
+    scratch = Aerodynamics->GetCoefficientValues(delimeter);
+    if (scratch.length() != 0) outstream << delimeter << scratch;
+  }
+  if (SubSystems & ssFCS) {
+    scratch = FCS->GetComponentValues(delimeter);
+    if (scratch.length() != 0) outstream << delimeter << scratch;
+  }
+  if (SubSystems & ssGroundReactions) {
+    outstream << delimeter;
+    outstream << GroundReactions->GetGroundReactionValues(delimeter);
+  }
+  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
+    outstream << delimeter;
+    outstream << Propulsion->GetPropulsionValues(delimeter);
+  }
+
+  for (unsigned int i=0;i<OutputProperties.size();i++) {
+    outstream << delimeter << OutputProperties[i]->getDoubleValue();
+  }
+
+  outstream << endl;
+  outstream.flush();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGOutput::SocketOutput(void)
+{
+  string asciiData, scratch;
+
+  if (socket == NULL) return;
+  if (!socket->GetConnectStatus()) return;
+
+  socket->Clear();
+  if (sFirstPass) {
+    socket->Clear("<LABELS>");
+    socket->Append("Time");
+
+    if (SubSystems & ssAerosurfaces) {
+      socket->Append("Aileron Command");
+      socket->Append("Elevator Command");
+      socket->Append("Rudder Command");
+      socket->Append("Flap Command");
+      socket->Append("Left Aileron Position");
+      socket->Append("Right Aileron Position");
+      socket->Append("Elevator Position");
+      socket->Append("Rudder Position");
+      socket->Append("Flap Position");
+    }
+
+    if (SubSystems & ssRates) {
+      socket->Append("P");
+      socket->Append("Q");
+      socket->Append("R");
+      socket->Append("PDot");
+      socket->Append("QDot");
+      socket->Append("RDot");
+    }
+
+    if (SubSystems & ssVelocities) {
+      socket->Append("QBar");
+      socket->Append("Vtotal");
+      socket->Append("UBody");
+      socket->Append("VBody");
+      socket->Append("WBody");
+      socket->Append("UAero");
+      socket->Append("VAero");
+      socket->Append("WAero");
+      socket->Append("Vn");
+      socket->Append("Ve");
+      socket->Append("Vd");
+    }
+    if (SubSystems & ssForces) {
+      socket->Append("F_Drag");
+      socket->Append("F_Side");
+      socket->Append("F_Lift");
+      socket->Append("LoD");
+      socket->Append("Fx");
+      socket->Append("Fy");
+      socket->Append("Fz");
+    }
+    if (SubSystems & ssMoments) {
+      socket->Append("L");
+      socket->Append("M");
+      socket->Append("N");
+    }
+    if (SubSystems & ssAtmosphere) {
+      socket->Append("Rho");
+      socket->Append("SL pressure");
+      socket->Append("Ambient pressure");
+      socket->Append("NWind");
+      socket->Append("EWind");
+      socket->Append("DWind");
+    }
+    if (SubSystems & ssMassProps) {
+      socket->Append("Ixx");
+      socket->Append("Ixy");
+      socket->Append("Ixz");
+      socket->Append("Iyx");
+      socket->Append("Iyy");
+      socket->Append("Iyz");
+      socket->Append("Izx");
+      socket->Append("Izy");
+      socket->Append("Izz");
+      socket->Append("Mass");
+      socket->Append("Xcg");
+      socket->Append("Ycg");
+      socket->Append("Zcg");
+    }
+    if (SubSystems & ssPropagate) {
+        socket->Append("Altitude");
+        socket->Append("Phi");
+        socket->Append("Tht");
+        socket->Append("Psi");
+        socket->Append("Alpha");
+        socket->Append("Beta");
+        socket->Append("Latitude (Deg)");
+        socket->Append("Longitude (Deg)");
+    }
+    if (SubSystems & ssCoefficients) {
+      scratch = Aerodynamics->GetCoefficientStrings(",");
+      if (scratch.length() != 0) socket->Append(scratch);
+    }
+    if (SubSystems & ssFCS) {
+      scratch = FCS->GetComponentStrings(",");
+      if (scratch.length() != 0) socket->Append(scratch);
+    }
+    if (SubSystems & ssGroundReactions) {
+      socket->Append(GroundReactions->GetGroundReactionStrings(","));
+    }
+    if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
+      socket->Append(Propulsion->GetPropulsionStrings(","));
+    }
+    if (OutputProperties.size() > 0) {
+      for (unsigned int i=0;i<OutputProperties.size();i++) {
+        socket->Append(OutputProperties[i]->GetName());
+      }
+    }
+
+    sFirstPass = false;
+    socket->Send();
+  }
+
+  socket->Clear();
+  socket->Append(State->Getsim_time());
+
+  if (SubSystems & ssAerosurfaces) {
+    socket->Append(FCS->GetDaCmd());
+    socket->Append(FCS->GetDeCmd());
+    socket->Append(FCS->GetDrCmd());
+    socket->Append(FCS->GetDfCmd());
+    socket->Append(FCS->GetDaLPos());
+    socket->Append(FCS->GetDaRPos());
+    socket->Append(FCS->GetDePos());
+    socket->Append(FCS->GetDrPos());
+    socket->Append(FCS->GetDfPos());
+  }
+  if (SubSystems & ssRates) {
+    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));
+  }
+  if (SubSystems & ssVelocities) {
+    socket->Append(Auxiliary->Getqbar());
+    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));
+  }
+  if (SubSystems & ssForces) {
+    socket->Append(Aerodynamics->GetvFs()(eDrag));
+    socket->Append(Aerodynamics->GetvFs()(eSide));
+    socket->Append(Aerodynamics->GetvFs()(eLift));
+    socket->Append(Aerodynamics->GetLoD());
+    socket->Append(Aircraft->GetForces(eX));
+    socket->Append(Aircraft->GetForces(eY));
+    socket->Append(Aircraft->GetForces(eZ));
+  }
+  if (SubSystems & ssMoments) {
+    socket->Append(Aircraft->GetMoments(eL));
+    socket->Append(Aircraft->GetMoments(eM));
+    socket->Append(Aircraft->GetMoments(eN));
+  }
+  if (SubSystems & ssAtmosphere) {
+    socket->Append(Atmosphere->GetDensity());
+    socket->Append(Atmosphere->GetPressureSL());
+    socket->Append(Atmosphere->GetPressure());
+    socket->Append(Atmosphere->GetWindNED().Dump(","));
+  }
+  if (SubSystems & ssMassProps) {
+    socket->Append(MassBalance->GetJ()(1,1));
+    socket->Append(MassBalance->GetJ()(1,2));
+    socket->Append(MassBalance->GetJ()(1,3));
+    socket->Append(MassBalance->GetJ()(2,1));
+    socket->Append(MassBalance->GetJ()(2,2));
+    socket->Append(MassBalance->GetJ()(2,3));
+    socket->Append(MassBalance->GetJ()(3,1));
+    socket->Append(MassBalance->GetJ()(3,2));
+    socket->Append(MassBalance->GetJ()(3,3));
+    socket->Append(MassBalance->GetMass());
+    socket->Append(MassBalance->GetXYZcg()(eX));
+    socket->Append(MassBalance->GetXYZcg()(eY));
+    socket->Append(MassBalance->GetXYZcg()(eZ));
+  }
+  if (SubSystems & ssPropagate) {
+    socket->Append(Propagate->Geth());
+    socket->Append(Propagate->GetEuler(ePhi));
+    socket->Append(Propagate->GetEuler(eTht));
+    socket->Append(Propagate->GetEuler(ePsi));
+    socket->Append(Auxiliary->Getalpha(inDegrees));
+    socket->Append(Auxiliary->Getbeta(inDegrees));
+    socket->Append(Propagate->GetLocation().GetLatitudeDeg());
+    socket->Append(Propagate->GetLocation().GetLongitudeDeg());
+  }
+  if (SubSystems & ssCoefficients) {
+    scratch = Aerodynamics->GetCoefficientValues(",");
+    if (scratch.length() != 0) socket->Append(scratch);
+  }
+  if (SubSystems & ssFCS) {
+    scratch = FCS->GetComponentValues(",");
+    if (scratch.length() != 0) socket->Append(scratch);
+  }
+  if (SubSystems & ssGroundReactions) {
+    socket->Append(GroundReactions->GetGroundReactionValues(","));
+  }
+  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
+    socket->Append(Propulsion->GetPropulsionValues(","));
+  }
+
+  for (unsigned int i=0;i<OutputProperties.size();i++) {
+    socket->Append(OutputProperties[i]->getDoubleValue());
+  }
+
+  socket->Send();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGOutput::SocketStatusOutput(string out_str)
+{
+  string asciiData;
+
+  if (socket == NULL) return;
+
+  socket->Clear();
+  asciiData = string("<STATUS>") + out_str;
+  socket->Append(asciiData.c_str());
+  socket->Send();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGOutput::Load(Element* element)
+{
+  string type="", parameter="";
+  string name="", fname="";
+  int OutRate = 0;
+  string property;
+  unsigned int port;
+  FGXMLParse output_file_parser;
+  Element *document, *property_element;
+  ifstream* output_file = new ifstream();
+
+  string separator = "/";
+# ifdef macintosh
+  separator = ";";
+# endif
+
+  fname = element->GetAttributeValue("file");
+  if (!fname.empty()) {
+    output_file_name = FDMExec->GetAircraftPath() + separator
+                        + FDMExec->GetModelName() + separator + fname + ".xml";
+
+    output_file->open(output_file_name.c_str());
+    readXML(*output_file, output_file_parser);
+    delete output_file;
+    document = output_file_parser.GetDocument();
+  } else {
+    document = element;
+  }
+
+  name = document->GetAttributeValue("name");
+  type = document->GetAttributeValue("type");
+  SetType(type);
+  if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) {
+    port = atoi(document->GetAttributeValue("port").c_str());
+    socket = new FGfdmSocket(name, port);
+  } else {
+    Filename = name;
+  }
+  if (!document->GetAttributeValue("rate").empty()) {
+    OutRate = (int)document->GetAttributeValueAsNumber("rate");
+  } else {
+    OutRate = 1;
+  }
+
+  if (document->FindElementValue("simulation") == string("ON"))
+    SubSystems += ssSimulation;
+  if (document->FindElementValue("aerosurfaces") == string("ON"))
+    SubSystems += ssAerosurfaces;
+  if (document->FindElementValue("rates") == string("ON"))
+    SubSystems += ssRates;
+  if (document->FindElementValue("velocities") == string("ON"))
+    SubSystems += ssVelocities;
+  if (document->FindElementValue("forces") == string("ON"))
+    SubSystems += ssForces;
+  if (document->FindElementValue("moments") == string("ON"))
+    SubSystems += ssMoments;
+  if (document->FindElementValue("atmosphere") == string("ON"))
+    SubSystems += ssAtmosphere;
+  if (document->FindElementValue("massprops") == string("ON"))
+    SubSystems += ssMassProps;
+  if (document->FindElementValue("position") == string("ON"))
+    SubSystems += ssPropagate;
+  if (document->FindElementValue("coefficients") == string("ON"))
+    SubSystems += ssCoefficients;
+  if (document->FindElementValue("ground_reactions") == string("ON"))
+    SubSystems += ssGroundReactions;
+  if (document->FindElementValue("fcs") == string("ON"))
+    SubSystems += ssFCS;
+  if (document->FindElementValue("propulsion") == string("ON"))
+    SubSystems += ssPropulsion;
+  property_element = document->FindElement("property");
+  while (property_element) {
+    string property = property_element->GetDataLine();
+    OutputProperties.push_back(PropertyManager->GetNode(property));
+    property_element = document->FindNextElement("property");
+  }
+
+  OutRate = OutRate>120?120:(OutRate<0?0:OutRate);
+  rate = (int)(0.5 + 1.0/(State->Getdt()*OutRate));
+
+  Debug(2);
+
+  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 FGOutput::Debug(int from)
+{
+  string scratch="";
+
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+
+    }
+    if (from == 2) {
+      if (output_file_name.empty())
+        cout << "  " << "Output parameters read inline" << endl;
+      else
+        cout << "    Output parameters read from file: " << output_file_name << endl;
+
+      if (Filename == "cout" || Filename == "COUT") {
+        scratch = "    Log output goes to screen console";
+      } else if (!Filename.empty()) {
+        scratch = "    Log output goes to file: " + Filename;
+      }
+      switch (Type) {
+      case otCSV:
+        cout << scratch << " in CSV format output at rate " << 120/rate << " Hz" << endl;
+        break;
+      case otNone:
+        cout << "  No log output" << endl;
+        break;
+      }
+
+      if (SubSystems & ssSimulation)      cout << "    Simulation parameters logged" << endl;
+      if (SubSystems & ssAerosurfaces)    cout << "    Aerosurface parameters logged" << endl;
+      if (SubSystems & ssRates)           cout << "    Rate parameters logged" << endl;
+      if (SubSystems & ssVelocities)      cout << "    Velocity parameters logged" << endl;
+      if (SubSystems & ssForces)          cout << "    Force parameters logged" << endl;
+      if (SubSystems & ssMoments)         cout << "    Moments parameters logged" << endl;
+      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 & 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
+    if (from == 0) cout << "Instantiated: FGOutput" << endl;
+    if (from == 1) cout << "Destroyed:    FGOutput" << 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/models/FGOutput.h b/src/FDM/JSBSim/models/FGOutput.h
new file mode 100644 (file)
index 0000000..35bc338
--- /dev/null
@@ -0,0 +1,174 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGOutput.h
+ Author:       Jon Berndt
+ Date started: 12/2/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 FGOUTPUT_H
+#define FGOUTPUT_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGModel.h"
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_IOSTREAM
+#  include STL_FSTREAM
+#else
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <iostream.h>
+#    include <fstream.h>
+#  else
+#    include <iostream>
+#    include <fstream>
+#  endif
+#endif
+
+#include <input_output/FGfdmSocket.h>
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_OUTPUT "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGOutput : public FGModel
+{
+public:
+  FGOutput(FGFDMExec*);
+  ~FGOutput();
+
+  bool Run(void);
+
+  void DelimitedOutput(string);
+  void SocketOutput(void);
+  void SocketStatusOutput(string);
+  void SetType(string);
+  void SetSubsystems(int tt) {SubSystems = tt;}
+  inline void Enable(void) { enabled = true; }
+  inline void Disable(void) { enabled = false; }
+  inline bool Toggle(void) {enabled = !enabled; return enabled;}
+  bool Load(Element* el);
+
+  /// Subsystem types for specifying which will be output in the FDM data logging
+  enum  eSubSystems {
+    /** Subsystem: Simulation (= 1)          */ ssSimulation      = 1,
+    /** Subsystem: Aerosurfaces (= 2)        */ ssAerosurfaces    = 2,
+    /** Subsystem: Body rates (= 4)          */ ssRates           = 4,
+    /** Subsystem: Velocities (= 8)          */ ssVelocities      = 8,
+    /** Subsystem: Forces (= 16)             */ ssForces          = 16,
+    /** Subsystem: Moments (= 32)            */ ssMoments         = 32,
+    /** Subsystem: Atmosphere (= 64)         */ ssAtmosphere      = 64,
+    /** Subsystem: Mass Properties (= 128)   */ ssMassProps       = 128,
+    /** Subsystem: Coefficients (= 256)      */ ssCoefficients    = 256,
+    /** Subsystem: Propagate (= 512)         */ ssPropagate       = 512,
+    /** Subsystem: Ground Reactions (= 1024) */ ssGroundReactions = 1024,
+    /** Subsystem: FCS (= 2048)              */ ssFCS             = 2048,
+    /** Subsystem: Propulsion (= 4096)       */ ssPropulsion      = 4096
+  } subsystems;
+
+private:
+  bool sFirstPass, dFirstPass, enabled;
+  int SubSystems;
+  string output_file_name, delimeter, Filename;
+  enum {otNone, otCSV, otTab, otSocket, otTerminal, otUnknown} Type;
+  ofstream datafile;
+  FGfdmSocket* socket;
+  vector <FGPropertyManager*> OutputProperties;
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/FGPropagate.cpp b/src/FDM/JSBSim/models/FGPropagate.cpp
new file mode 100644 (file)
index 0000000..fcd7861
--- /dev/null
@@ -0,0 +1,418 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 <input_output/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 = SeaLevelRadius;
+
+  // 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;
+
+  // Finally, make sure that the quaternion stays normalized.
+  VState.vQtrn.Normalize();
+
+  // Recompute the RunwayRadius level.
+  RecomputeRunwayRadius();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/*
+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 ...
+  if (FDMExec->Holding()) return false;
+
+  RecomputeRunwayRadius();
+
+  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;
+
+  // Coriolis acceleration.
+  FGColumnVector3 ecVel = Tl2ec*vVel;
+  FGColumnVector3 ace = 2.0*omega*ecVel;
+  vUVWdot -= Tl2b*(Tec2l*ace);
+
+  if (!GroundReactions->GetWOW()) {
+    // Centrifugal 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::RecomputeRunwayRadius(void)
+{
+  // Get the runway radius.
+  FGLocation contactloc;
+  FGColumnVector3 dv;
+  FGGroundCallback* gcb = FDMExec->GetGroundCallback();
+  double t = State->Getsim_time();
+  gcb->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
+  RunwayRadius = contactloc.GetRadius();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::Seth(double tt)
+{
+  VState.vLocation.SetRadius( tt + SeaLevelRadius );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGPropagate::GetRunwayRadius(void) const
+{
+  return RunwayRadius;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGPropagate::GetDistanceAGL(void) const
+{
+  return VState.vLocation.GetRadius() - RunwayRadius;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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);
+
+  PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
+  PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
+  PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
+
+  PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
+  PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
+  PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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/models/FGPropagate.h b/src/FDM/JSBSim/models/FGPropagate.h
new file mode 100644 (file)
index 0000000..2c0fef1
--- /dev/null
@@ -0,0 +1,166 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 <models/FGModel.h>
+#include <math/FGColumnVector3.h>
+#include <initialization/FGInitialCondition.h>
+#include <math/FGLocation.h>
+#include <math/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 GetCosEuler(int idx) const { return VState.vQtrn.GetCosEuler(idx); }
+  double GetSinEuler(int idx) const { return VState.vQtrn.GetSinEuler(idx); }
+  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;
+  double GetSeaLevelRadius(void) const { return SeaLevelRadius; }
+  double GetDistanceAGL(void)  const;
+  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; }
+
+  /** 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 SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; }
+  void SetDistanceAGL(double tt);
+  void SetInitialState(const FGInitialCondition *);
+  void RecomputeRunwayRadius(void);
+
+  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
diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp
new file mode 100644 (file)
index 0000000..306126c
--- /dev/null
@@ -0,0 +1,632 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGPropulsion.cpp
+ Author:       Jon S. Berndt
+ Date started: 08/20/00
+ Purpose:      Encapsulates the set of engines and tanks associated
+               with this aircraft
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+The Propulsion class is the container for the entire propulsion system, which is
+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) At least one tank object is created, and is linked to an engine.
+
+At Run time each engines Calculate() method is called.
+
+HISTORY
+--------------------------------------------------------------------------------
+08/20/00   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGPropulsion.h"
+#include <models/propulsion/FGRocket.h>
+#include <models/propulsion/FGTurbine.h>
+#include <models/propulsion/FGPiston.h>
+#include <models/propulsion/FGElectric.h>
+#include <models/propulsion/FGTurboProp.h>
+#include <input_output/FGPropertyManager.h>
+#include <input_output/FGXMLParse.h>
+#include <math/FGColumnVector3.h>
+#include <sstream>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_PROPULSION;
+
+extern short debug_lvl;
+
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
+{
+  Name = "FGPropulsion";
+
+  numSelectedFuelTanks = numSelectedOxiTanks = 0;
+  numTanks = numEngines = 0;
+  numOxiTanks = numFuelTanks = 0;
+  ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
+  tankJ.InitMatrix();
+  refuel = false;
+  fuel_freeze = false;
+  TotalFuelQuantity = 0.0;
+  IsBound =
+  HavePistonEngine =
+  HaveTurbineEngine =
+  HaveRocketEngine =
+  HaveTurboPropEngine =
+  HaveElectricEngine = false;
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPropulsion::~FGPropulsion()
+{
+  for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
+  Engines.clear();
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropulsion::Run(void)
+{
+  unsigned int i;
+
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  double dt = State->Getdt();
+
+  vForces.InitMatrix();
+  vMoments.InitMatrix();
+
+  for (i=0; i<numEngines; i++) {
+    Engines[i]->Calculate();
+    vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
+    vMoments += Engines[i]->GetMoments();     // sum body frame moments
+  }
+
+  TotalFuelQuantity = 0.0;
+  for (i=0; i<numTanks; i++) {
+    Tanks[i]->Calculate( dt * rate );
+    if (Tanks[i]->GetType() == FGTank::ttFUEL) {
+      TotalFuelQuantity += Tanks[i]->GetContents();
+    } 
+  }
+
+  if (refuel) DoRefuel( dt * rate );
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropulsion::GetSteadyState(void)
+{
+  double currentThrust = 0, lastThrust=-1;
+  int steady_count,j=0;
+  bool steady=false;
+
+  vForces.InitMatrix();
+  vMoments.InitMatrix();
+
+  if (!FGModel::Run()) {
+    for (unsigned int i=0; i<numEngines; i++) {
+      Engines[i]->SetTrimMode(true);
+      steady=false;
+      steady_count=0;
+      while (!steady && j < 6000) {
+        Engines[i]->Calculate();
+        lastThrust = currentThrust;
+        currentThrust = Engines[i]->GetThrust();
+        if (fabs(lastThrust-currentThrust) < 0.0001) {
+          steady_count++;
+          if (steady_count > 120) { steady=true; }
+        } else {
+          steady_count=0;
+        }
+        j++;
+      }
+      vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
+      vMoments += Engines[i]->GetMoments();     // sum body frame moments
+      Engines[i]->SetTrimMode(false);
+    }
+
+    return false;
+  } else {
+    return true;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropulsion::ICEngineStart(void)
+{
+  int j;
+
+  vForces.InitMatrix();
+  vMoments.InitMatrix();
+
+  for (unsigned int i=0; i<numEngines; i++) {
+    Engines[i]->SetTrimMode(true);
+    j=0;
+    while (!Engines[i]->GetRunning() && j < 2000) {
+      Engines[i]->Calculate();
+      j++;
+    }
+    vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
+    vMoments += Engines[i]->GetMoments();     // sum body frame moments
+    Engines[i]->SetTrimMode(false);
+  }
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPropulsion::Load(Element* el)
+{
+  string type, engine_filename;
+  int Feed;
+  bool ThrottleAdded = false;
+  Element* document;
+  FGXMLParse engine_file_parser;
+  ifstream* engine_file;
+
+  Debug(2);
+
+  Element* engine_element = el->FindElement("engine");
+  while (engine_element) {
+    engine_filename = engine_element->GetAttributeValue("file");
+
+    if (engine_filename.empty()) {
+      cerr << "Engine definition did not supply an engine file." << endl;
+      return false;
+    }
+
+    engine_filename = FindEngineFullPathname(engine_filename);
+    readXML(engine_filename, engine_file_parser);
+    document = engine_file_parser.GetDocument(); // document holds the engine description
+    document->SetParent(engine_element);
+
+    type = document->GetName();
+    if (type == "piston_engine") {
+      HavePistonEngine = true;
+      if (!IsBound) bind();
+      Engines.push_back(new FGPiston(FDMExec, document, numEngines));
+    } else if (type == "turbine_engine") {
+      HaveTurbineEngine = true;
+      if (!IsBound) bind();
+      Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
+    } else if (type == "turboprop_engine") {
+      HaveTurboPropEngine = true;
+      if (!IsBound) bind();
+      Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
+    } else if (type == "rocket_engine") {
+      HaveRocketEngine = true;
+      if (!IsBound) bind();
+      Engines.push_back(new FGRocket(FDMExec, document, numEngines));
+    } else if (type == "electric_engine") {
+      HaveElectricEngine = true;
+      if (!IsBound) bind();
+      Engines.push_back(new FGElectric(FDMExec, document, numEngines));
+    } else {
+      cerr << "Unknown engine type: " << type << endl;
+      exit(-5);
+    }
+
+    FCS->AddThrottle();
+    ThrottleAdded = true;
+
+    numEngines++;
+
+    engine_element = el->FindNextElement("engine");
+    engine_file_parser.reset();
+  }
+
+  // Process tank definitions
+
+  Element* tank_element = el->FindElement("tank");
+  while (tank_element) {
+    Tanks.push_back(new FGTank(FDMExec, tank_element));
+    if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
+    else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
+    else {cerr << "Unknown tank type specified." << endl; return false;}
+    numTanks++;
+    tank_element = el->FindNextElement("tank");
+  }
+  numSelectedFuelTanks = numFuelTanks;
+  numSelectedOxiTanks  = numOxiTanks;
+
+  CalculateTankInertias();
+  if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropulsion::FindEngineFullPathname(string engine_filename)
+{
+  string fullpath, localpath;
+  string enginePath = FDMExec->GetEnginePath();
+  string aircraftPath = FDMExec->GetAircraftPath();
+  ifstream* engine_file = new ifstream();
+
+  string separator = "/";
+# ifdef macintosh
+  separator = ";";
+# endif
+
+  fullpath = enginePath + separator;
+  localpath = aircraftPath + separator + "Engines" + separator;
+
+  engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
+  if ( !engine_file->is_open()) {
+    engine_file->open(string(localpath + engine_filename + ".xml").c_str());
+      if ( !engine_file->is_open()) {
+        cerr << " Could not open engine file: " << engine_filename << " in path "
+             << fullpath << " or " << localpath << endl;
+        return string("");
+      } else {
+        return string(localpath + engine_filename + ".xml");
+      }
+  }
+  return string(fullpath + engine_filename + ".xml");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ifstream* FGPropulsion::FindEngineFile(string engine_filename)
+{
+  string fullpath, localpath;
+  string enginePath = FDMExec->GetEnginePath();
+  string aircraftPath = FDMExec->GetAircraftPath();
+  ifstream* engine_file = new ifstream();
+
+  string separator = "/";
+# ifdef macintosh
+  separator = ";";
+# endif
+
+  fullpath = enginePath + separator;
+  localpath = aircraftPath + separator + "Engines" + separator;
+
+  engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
+  if ( !engine_file->is_open()) {
+    engine_file->open(string(localpath + engine_filename + ".xml").c_str());
+      if ( !engine_file->is_open()) {
+        cerr << " Could not open engine file: " << engine_filename << " in path "
+             << fullpath << " or " << localpath << endl;
+      }
+  }
+  return engine_file;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropulsion::GetPropulsionStrings(string delimeter)
+{
+  unsigned int i;
+
+  string PropulsionStrings = "";
+  bool firstime = true;
+  stringstream buf;
+
+  for (i=0; i<Engines.size(); i++) {
+    if (firstime)  firstime = false;
+    else           PropulsionStrings += delimeter;
+
+    PropulsionStrings += Engines[i]->GetEngineLabels(delimeter);
+  }
+  for (i=0; i<Tanks.size(); i++) {
+    if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i;
+    else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i;
+  }
+
+  return PropulsionStrings;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropulsion::GetPropulsionValues(string delimeter)
+{
+  unsigned int i;
+
+  string PropulsionValues = "";
+  bool firstime = true;
+  stringstream buf;
+
+  for (i=0; i<Engines.size(); i++) {
+    if (firstime)  firstime = false;
+    else           PropulsionValues += delimeter;
+
+    PropulsionValues += Engines[i]->GetEngineValues(delimeter);
+  }
+  for (i=0; i<Tanks.size(); i++) {
+    buf << delimeter;
+    buf << Tanks[i]->GetContents();
+  }
+
+  return PropulsionValues;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGPropulsion::GetTanksMoment(void)
+{
+  iTank = Tanks.begin();
+  vXYZtank_arm.InitMatrix();
+  while (iTank < Tanks.end()) {
+    vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents();
+    vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents();
+    vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents();
+    iTank++;
+  }
+  return vXYZtank_arm;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGPropulsion::GetTanksWeight(void)
+{
+  double Tw = 0.0;
+
+  iTank = Tanks.begin();
+  while (iTank < Tanks.end()) {
+    Tw += (*iTank)->GetContents();
+    iTank++;
+  }
+  return Tw;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33& FGPropulsion::CalculateTankInertias(void)
+{
+  unsigned int size;
+
+  size = Tanks.size();
+  if (size == 0) return tankJ;
+
+  tankJ = FGMatrix33();
+
+  for (unsigned int i=0; i<size; i++)
+    tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
+                                               Tanks[i]->GetXYZ() );
+
+  return tankJ;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::SetMagnetos(int setting)
+{
+  if (ActiveEngine < 0) {
+    for (unsigned i=0; i<Engines.size(); i++) {
+      // ToDo: first need to make sure the engine Type is really appropriate:
+      //   do a check to see if it is of type Piston. This should be done for
+      //   all of this kind of possibly across-the-board settings.
+      ((FGPiston*)Engines[i])->SetMagnetos(setting);
+    }
+  } else {
+    ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::SetStarter(int setting)
+{
+  if (ActiveEngine < 0) {
+    for (unsigned i=0; i<Engines.size(); i++) {
+      if (setting == 0)
+        Engines[i]->SetStarter(false);
+      else
+        Engines[i]->SetStarter(true);
+    }
+  } else {
+    if (setting == 0)
+      Engines[ActiveEngine]->SetStarter(false);
+    else
+      Engines[ActiveEngine]->SetStarter(true);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::SetCutoff(int setting)
+{
+  if (ActiveEngine < 0) {
+    for (unsigned i=0; i<Engines.size(); i++) {
+      if (setting == 0)
+        ((FGTurbine*)Engines[i])->SetCutoff(false);
+      else
+        ((FGTurbine*)Engines[i])->SetCutoff(true);
+    }
+  } else {
+    if (setting == 0)
+      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
+    else
+      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::SetActiveEngine(int engine)
+{
+  if (engine >= Engines.size() || engine < 0)
+    ActiveEngine = -1;
+  else
+    ActiveEngine = 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)
+{
+  unsigned int i;
+
+  double fillrate = 100 * time_slice;   // 100 lbs/sec = 6000 lbs/min
+  int TanksNotFull = 0;
+
+  for (i=0; i<numTanks; i++) {
+    if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
+  }
+
+  if (TanksNotFull) {
+    for (i=0; i<numTanks; i++) {
+      if (Tanks[i]->GetPctFull() < 99.99)
+          Transfer(-1, i, fillrate/TanksNotFull);
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::SetFuelFreeze(bool f)
+{
+  fuel_freeze = f;
+  for (unsigned int i=0; i<numEngines; i++) {
+    Engines[i]->SetFuelFreeze(f);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::bind(void)
+{
+  typedef double (FGPropulsion::*PMF)(int) const;
+  typedef int (FGPropulsion::*iPMF)(void) const;
+
+  IsBound = true;
+
+  if (HaveTurbineEngine) {
+    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
+    PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   true);
+  }
+
+  if (HavePistonEngine) {
+    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
+    PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
+  }
+
+  PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
+                        &FGPropulsion::SetActiveEngine, true);
+  PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropulsion::unbind(void)
+{
+  if (HaveTurbineEngine) {
+    PropertyManager->Untie("propulsion/starter_cmd");
+    PropertyManager->Untie("propulsion/cutoff_cmd");
+  }
+  if (HavePistonEngine) {
+    PropertyManager->Untie("propulsion/starter_cmd");
+    PropertyManager->Untie("propulsion/magneto_cmd");
+  }
+  PropertyManager->Untie("propulsion/active_engine");
+  PropertyManager->Untie("propulsion/total-fuel-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
+//       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 FGPropulsion::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 2) { // Loader
+      cout << endl << "  Propulsion:" << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
+    if (from == 1) cout << "Destroyed:    FGPropulsion" << 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/models/FGPropulsion.h b/src/FDM/JSBSim/models/FGPropulsion.h
new file mode 100644 (file)
index 0000000..6ae3324
--- /dev/null
@@ -0,0 +1,219 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGPropulsion.h
+ Author:       Jon S. Berndt
+ Date started: 08/20/00
+
+ ------------- 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
+--------------------------------------------------------------------------------
+08/20/00   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGPROPULSION_H
+#define FGPROPULSION_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#    include <iterator>
+#    include <fstream>
+#  else
+#    include <vector.h>
+#    include <iterator.h>
+#    include <fstream.h>
+#  endif
+#else
+#  include <vector>
+#  include <iterator>
+#  include <fstream>
+#endif
+
+#include "FGModel.h"
+#include <models/propulsion/FGEngine.h>
+#include <models/propulsion/FGTank.h>
+#include <math/FGMatrix33.h>
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_PROPULSION "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Propulsion management class.
+    The Propulsion class is the container for the entire propulsion system, which is
+    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
+    -# At least one tank object is created, and is linked to an engine.
+
+    At Run time each engines Calculate() method is called.
+    @author Jon S. Berndt
+    @version $Id$
+    @see
+    FGEngine
+    FGTank
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGPropulsion : public FGModel
+{
+public:
+  /// Constructor
+  FGPropulsion(FGFDMExec*);
+  /// Destructor
+  ~FGPropulsion();
+
+  /** Executes the propulsion model.
+      The initial plan for the FGPropulsion class calls for Run() to be executed,
+      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] and tank[s]).
+      Characteristics of the propulsion system are read in from the config file.
+      @param el pointer to an XML element that contains the engine information.
+      @return true if successfully loaded, otherwise false */
+  bool Load(Element* el);
+
+  /// Retrieves the number of engines defined for the aircraft.
+  inline unsigned int GetNumEngines(void) const {return Engines.size();}
+
+  /** Retrieves an engine object pointer from the list of engines.
+      @param index the engine index within the vector container
+      @return the address of the specific engine, or zero if no such engine is
+              available */
+  inline FGEngine* GetEngine(unsigned int index) {
+                      if (index <= Engines.size()-1) return Engines[index];
+                      else                           return 0L;      }
+
+  /// Retrieves the number of tanks defined for the aircraft.
+  inline unsigned int GetNumTanks(void) const {return Tanks.size();}
+
+  /** Retrieves a tank object pointer from the list of tanks.
+      @param index the tank index within the vector container
+      @return the address of the specific tank, or zero if no such tank is
+              available */
+  inline FGTank* GetTank(unsigned int index) {
+                      if (index <= Tanks.size()-1) return Tanks[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 until thrust output steady (used for trimming) */
+  bool GetSteadyState(void);
+
+  /** starts the engines in IC mode (dt=0).  All engine-specific setup must
+      be done before calling this (i.e. magnetos, starter engage, etc.) */
+  bool ICEngineStart(void);
+
+  string GetPropulsionStrings(string delimeter);
+  string GetPropulsionValues(string delimeter);
+
+  inline FGColumnVector3& GetForces(void)  {return vForces; }
+  inline double GetForces(int n) const { return vForces(n);}
+  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);
+
+  ifstream* FindEngineFile(string filename);
+  string FindEngineFullPathname(string engine_filename);
+  inline int GetActiveEngine(void) const {return ActiveEngine;}
+  inline bool GetFuelFreeze(void) {return fuel_freeze;}
+  double GetTotalFuelQuantity(void) const {return TotalFuelQuantity;}
+
+  void SetMagnetos(int setting);
+  void SetStarter(int setting);
+  void SetCutoff(int setting=0);
+  void SetActiveEngine(int engine);
+  void SetFuelFreeze(bool f);
+  FGMatrix33& CalculateTankInertias(void);
+
+  void bind();
+  void unbind();
+
+private:
+  vector <FGEngine*>   Engines;
+  vector <FGTank*>     Tanks;
+  vector <FGTank*>::iterator iTank;
+  unsigned int numSelectedFuelTanks;
+  unsigned int numSelectedOxiTanks;
+  unsigned int numFuelTanks;
+  unsigned int numOxiTanks;
+  unsigned int numEngines;
+  unsigned int numTanks;
+  int ActiveEngine;
+  FGColumnVector3 vForces;
+  FGColumnVector3 vMoments;
+  FGColumnVector3 vTankXYZ;
+  FGColumnVector3 vXYZtank_arm;
+  FGMatrix33 tankJ;
+  bool refuel;
+  bool fuel_freeze;
+  double TotalFuelQuantity;
+  bool IsBound;
+  bool HavePistonEngine;
+  bool HaveTurbineEngine;
+  bool HaveTurboPropEngine;
+  bool HaveRocketEngine;
+  bool HaveElectricEngine;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/Makefile.am b/src/FDM/JSBSim/models/Makefile.am
new file mode 100644 (file)
index 0000000..10c65a7
--- /dev/null
@@ -0,0 +1,14 @@
+SUBDIRS = atmosphere propulsion flight_control
+
+noinst_LIBRARIES = libModels.a
+
+libModels_a_SOURCES = FGAerodynamics.cpp FGAircraft.cpp FGAtmosphere.cpp \
+                      FGAuxiliary.cpp FGFCS.cpp FGGroundReactions.cpp FGInertial.cpp \
+                      FGLGear.cpp FGMassBalance.cpp FGModel.cpp FGOutput.cpp \
+                      FGPropagate.cpp FGPropulsion.cpp FGInput.cpp
+
+noinst_HEADERS = FGAerodynamics.h FGAircraft.h FGAtmosphere.h FGAuxiliary.h \
+                 FGFCS.h FGGroundReactions.h FGInertial.h FGLGear.h FGMassBalance.h \
+                 FGModel.h FGOutput.h FGPropagate.h FGPropulsion.h FGInput.h 
+
+INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
diff --git a/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp b/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp
new file mode 100755 (executable)
index 0000000..1930b3f
--- /dev/null
@@ -0,0 +1,1667 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGMSIS.cpp
+ Author:       David Culp
+               (incorporated into C++ JSBSim class heirarchy, see model authors below)
+ Date started: 12/14/03
+ Purpose:      Models the MSIS-00 atmosphere
+
+ ------------- Copyright (C) 2003  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.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+Models the MSIS-00 atmosphere. Provides temperature and density to FGAtmosphere,
+given day-of-year, time-of-day, altitude, latitude, longitude and local time.
+
+HISTORY
+--------------------------------------------------------------------------------
+12/14/03   DPC   Created
+01/11/04   DPC   Derived from FGAtmosphere
+
+ --------------------------------------------------------------------
+ ---------  N R L M S I S E - 0 0    M O D E L    2 0 0 1  ----------
+ --------------------------------------------------------------------
+
+ This file is part of the NRLMSISE-00  C source code package - release
+ 20020503
+
+ The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and
+ Doug Drob. They also wrote a NRLMSISE-00 distribution package in
+ FORTRAN which is available at
+ http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm
+
+ Dominik Brodowski implemented and maintains this C version. You can
+ reach him at devel@brodo.de. See the file "DOCUMENTATION" for details,
+ and check http://www.brodo.de/english/pub/nrlmsise/index.html for
+ updated releases of this package.
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGMSIS.h"
+#include "FGState.h"
+#include <math.h>          /* maths functions */
+#include <stdlib.h>        /* for malloc/free */
+#include <stdio.h>         /* for printf      */
+#include <iostream>        // for cout, endl
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_MSIS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+EXTERNAL GLOBAL DATA
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+  /* POWER7 */
+  extern double pt[150];
+  extern double pd[9][150];
+  extern double ps[150];
+  extern double pdl[2][25];
+  extern double ptl[4][100];
+  extern double pma[10][100];
+  extern double sam[100];
+
+  /* LOWER7 */
+  extern double ptm[10];
+  extern double pdm[8][10];
+  extern double pavgm[10];
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+MSIS::MSIS(FGFDMExec* fdmex) : FGAtmosphere(fdmex)
+{
+  Name = "MSIS";
+  bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+MSIS::~MSIS()
+{
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool MSIS::InitModel(void)
+{
+  FGModel::InitModel();
+
+  unsigned int i;
+
+  flags.switches[0] = 0;
+  for (i=1;i<24;i++) flags.switches[i] = 1;
+
+  for (i=0;i<7;i++) aph.a[i] = 100.0;
+
+  // set some common magnetic flux values
+  input.f107A = 150.0;
+  input.f107 = 150.0;
+  input.ap = 4.0;
+
+  SLtemperature = intTemperature = 518.0;
+  SLpressure    = intPressure = 2116.7;
+  SLdensity     = intDensity = 0.002378;
+  SLsoundspeed  = sqrt(2403.0832 * SLtemperature);
+  rSLtemperature = 1.0/intTemperature;
+  rSLpressure    = 1.0/intPressure;
+  rSLdensity     = 1.0/intDensity;
+  rSLsoundspeed  = 1.0/SLsoundspeed;
+  temperature = &intTemperature;
+  pressure = &intPressure;
+  density = &intDensity;
+
+  useExternal=false;
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool MSIS::Run(void)
+{
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  //do temp, pressure, and density first
+  if (!useExternal) {
+    // get sea-level values
+    Calculate(Auxiliary->GetDayOfYear(),
+              Auxiliary->GetSecondsInDay(),
+              0.0,
+              Propagate->GetLocation().GetLatitudeDeg(),
+              Propagate->GetLocation().GetLongitudeDeg());
+    SLtemperature = output.t[1] * 1.8;
+    SLdensity     = output.d[5] * 1.940321;
+    SLpressure    = 1716.488 * SLdensity * SLtemperature;
+    SLsoundspeed  = sqrt(2403.0832 * SLtemperature);
+    rSLtemperature = 1.0/SLtemperature;
+    rSLpressure    = 1.0/SLpressure;
+    rSLdensity     = 1.0/SLdensity;
+    rSLsoundspeed  = 1.0/SLsoundspeed;
+
+    // get at-altitude values
+    Calculate(Auxiliary->GetDayOfYear(),
+              Auxiliary->GetSecondsInDay(),
+              Propagate->Geth(),
+              Propagate->GetLocation().GetLatitudeDeg(),
+              Propagate->GetLocation().GetLongitudeDeg());
+    intTemperature = output.t[1] * 1.8;
+    intDensity     = output.d[5] * 1.940321;
+    intPressure    = 1716.488 * intDensity * intTemperature;
+    soundspeed     = sqrt(2403.0832 * intTemperature);
+    //cout << "T=" << intTemperature << " D=" << intDensity << " P=";
+    //cout << intPressure << " a=" << soundspeed << endl;
+  }
+
+  if (turbType != ttNone) {
+    Turbulence();
+    vWindNED += vTurbulence;
+  }
+
+  if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) );
+
+  if (psiw < 0) psiw += 2*M_PI;
+
+  Debug(2);
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::Calculate(int day, double sec, double alt, double lat, double lon)
+{
+  input.year = 2000;
+  input.doy = day;
+  input.sec = sec;
+  input.alt = alt / 3281;  //feet to kilometers
+  input.g_lat = lat;
+  input.g_long = lon;
+
+  input.lst = (sec/3600) + (lon/15);
+  if (input.lst > 24.0) input.lst -= 24.0;
+  if (input.lst < 0.0) input.lst = 24 - input.lst;
+
+  gtd7d(&input, &flags, &output);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+void MSIS::UseExternal(void){
+  // do nothing, external control not allowed
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+void MSIS::tselec(struct nrlmsise_flags *flags)
+{
+  int i;
+  for (i=0;i<24;i++) {
+    if (i!=9) {
+      if (flags->switches[i]==1)
+        flags->sw[i]=1;
+      else
+        flags->sw[i]=0;
+      if (flags->switches[i]>0)
+        flags->swc[i]=1;
+      else
+        flags->swc[i]=0;
+    } else {
+      flags->sw[i]=flags->switches[i];
+      flags->swc[i]=flags->switches[i];
+    }
+  }
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::glatf(double lat, double *gv, double *reff)
+{
+  double dgtr = 1.74533E-2;
+  double c2;
+  c2 = cos(2.0*dgtr*lat);
+  *gv = 980.616 * (1.0 - 0.0026373 * c2);
+  *reff = 2.0 * (*gv) / (3.085462E-6 + 2.27E-9 * c2) * 1.0E-5;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::ccor(double alt, double r, double h1, double zh)
+{
+/*        CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS
+ *         ALT - altitude
+ *         R - target ratio
+ *         H1 - transition scale length
+ *         ZH - altitude of 1/2 R
+ */
+  double e;
+  double ex;
+  e = (alt - zh) / h1;
+  if (e>70)
+    return exp(0.0);
+  if (e<-70)
+    return exp(r);
+  ex = exp(e);
+  e = r / (1.0 + ex);
+  return exp(e);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::ccor2(double alt, double r, double h1, double zh, double h2)
+{
+/*        CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS
+ *         ALT - altitude
+ *         R - target ratio
+ *         H1 - transition scale length
+ *         ZH - altitude of 1/2 R
+ *         H2 - transition scale length #2 ?
+ */
+  double e1, e2;
+  double ex1, ex2;
+  double ccor2v;
+  e1 = (alt - zh) / h1;
+  e2 = (alt - zh) / h2;
+  if ((e1 > 70) || (e2 > 70))
+    return exp(0.0);
+  if ((e1 < -70) && (e2 < -70))
+    return exp(r);
+  ex1 = exp(e1);
+  ex2 = exp(e2);
+  ccor2v = r / (1.0 + 0.5 * (ex1 + ex2));
+  return exp(ccor2v);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::scalh(double alt, double xm, double temp)
+{
+  double g;
+  double rgas=831.4;
+  g = gsurf / (pow((1.0 + alt/re),2.0));
+  g = rgas * temp / (g * xm);
+  return g;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::dnet (double dd, double dm, double zhm, double xmm, double xm)
+{
+/*       TURBOPAUSE CORRECTION FOR MSIS MODELS
+ *        Root mean density
+ *         DD - diffusive density
+ *         DM - full mixed density
+ *         ZHM - transition scale length
+ *         XMM - full mixed molecular weight
+ *         XM  - species molecular weight
+ *         DNET - combined density
+ */
+  double a;
+  double ylog;
+  a  = zhm / (xmm-xm);
+  if (!((dm>0) && (dd>0))) {
+    printf("dnet log error %e %e %e\n",dm,dd,xm);
+    if ((dd==0) && (dm==0))
+      dd=1;
+    if (dm==0)
+      return dd;
+    if (dd==0)
+      return dm;
+  }
+  ylog = a * log(dm/dd);
+  if (ylog<-10)
+    return dd;
+  if (ylog>10)
+    return dm;
+  a = dd*pow((1.0 + exp(ylog)),(1.0/a));
+  return a;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::splini (double *xa, double *ya, double *y2a, int n, double x, double *y)
+{
+/*      INTEGRATE CUBIC SPLINE FUNCTION FROM XA(1) TO X
+ *       XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X
+ *       Y2A: ARRAY OF SECOND DERIVATIVES
+ *       N: SIZE OF ARRAYS XA,YA,Y2A
+ *       X: ABSCISSA ENDPOINT FOR INTEGRATION
+ *       Y: OUTPUT VALUE
+ */
+  double yi=0;
+  int klo=0;
+  int khi=1;
+  double xx, h, a, b, a2, b2;
+  while ((x>xa[klo]) && (khi<n)) {
+    xx=x;
+    if (khi<(n-1)) {
+      if (x<xa[khi])
+        xx=x;
+      else
+        xx=xa[khi];
+    }
+    h = xa[khi] - xa[klo];
+    a = (xa[khi] - xx)/h;
+    b = (xx - xa[klo])/h;
+    a2 = a*a;
+    b2 = b*b;
+    yi += ((1.0 - a2) * ya[klo] / 2.0 + b2 * ya[khi] / 2.0 + ((-(1.0+a2*a2)/4.0 + a2/2.0) * y2a[klo] + (b2*b2/4.0 - b2/2.0) * y2a[khi]) * h * h / 6.0) * h;
+    klo++;
+    khi++;
+  }
+  *y = yi;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::splint (double *xa, double *ya, double *y2a, int n, double x, double *y)
+{
+/*      CALCULATE CUBIC SPLINE INTERP VALUE
+ *       ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL.
+ *       XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X
+ *       Y2A: ARRAY OF SECOND DERIVATIVES
+ *       N: SIZE OF ARRAYS XA,YA,Y2A
+ *       X: ABSCISSA FOR INTERPOLATION
+ *       Y: OUTPUT VALUE
+ */
+  int klo=0;
+  int khi=n-1;
+  int k;
+  double h;
+  double a, b, yi;
+  while ((khi-klo)>1) {
+    k=(khi+klo)/2;
+    if (xa[k]>x)
+      khi=k;
+    else
+      klo=k;
+  }
+  h = xa[khi] - xa[klo];
+  if (h==0.0)
+    printf("bad XA input to splint");
+  a = (xa[khi] - x)/h;
+  b = (x - xa[klo])/h;
+  yi = a * ya[klo] + b * ya[khi] + ((a*a*a - a) * y2a[klo] + (b*b*b - b) * y2a[khi]) * h * h/6.0;
+  *y = yi;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::spline (double *x, double *y, int n, double yp1, double ypn, double *y2)
+{
+/*       CALCULATE 2ND DERIVATIVES OF CUBIC SPLINE INTERP FUNCTION
+ *       ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL
+ *       X,Y: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X
+ *       N: SIZE OF ARRAYS X,Y
+ *       YP1,YPN: SPECIFIED DERIVATIVES AT X[0] AND X[N-1]; VALUES
+ *                >= 1E30 SIGNAL SIGNAL SECOND DERIVATIVE ZERO
+ *       Y2: OUTPUT ARRAY OF SECOND DERIVATIVES
+ */
+  double *u;
+  double sig, p, qn, un;
+  int i, k;
+  u=(double*)malloc(sizeof(double)*n);
+  if (u==NULL) {
+    printf("Out Of Memory in spline - ERROR");
+    return;
+  }
+  if (yp1>0.99E30) {
+    y2[0]=0;
+    u[0]=0;
+  } else {
+    y2[0]=-0.5;
+    u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yp1);
+  }
+  for (i=1;i<(n-1);i++) {
+    sig = (x[i]-x[i-1])/(x[i+1] - x[i-1]);
+    p = sig * y2[i-1] + 2.0;
+    y2[i] = (sig - 1.0) / p;
+    u[i] = (6.0 * ((y[i+1] - y[i])/(x[i+1] - x[i]) -(y[i] - y[i-1]) / (x[i] - x[i-1]))/(x[i+1] - x[i-1]) - sig * u[i-1])/p;
+  }
+  if (ypn>0.99E30) {
+    qn = 0;
+    un = 0;
+  } else {
+    qn = 0.5;
+    un = (3.0 / (x[n-1] - x[n-2])) * (ypn - (y[n-1] - y[n-2])/(x[n-1] - x[n-2]));
+  }
+  y2[n-1] = (un - qn * u[n-2]) / (qn * y2[n-2] + 1.0);
+  for (k=n-2;k>=0;k--)
+    y2[k] = y2[k] * y2[k+1] + u[k];
+
+  free(u);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::zeta(double zz, double zl)
+{
+  return ((zz-zl)*(re+zl)/(re+zz));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::densm(double alt, double d0, double xm, double *tz, int mn3,
+                     double *zn3, double *tn3, double *tgn3, int mn2, double *zn2,
+                     double *tn2, double *tgn2)
+{
+/*      Calculate Temperature and Density Profiles for lower atmos.  */
+  double xs[10], ys[10], y2out[10];
+  double rgas = 831.4;
+  double z, z1, z2, t1, t2, zg, zgdif;
+  double yd1, yd2;
+  double x, y, yi;
+  double expl, gamm, glb;
+  double densm_tmp;
+  int mn;
+  int k;
+  densm_tmp=d0;
+  if (alt>zn2[0]) {
+    if (xm==0.0)
+      return *tz;
+    else
+      return d0;
+  }
+
+  /* STRATOSPHERE/MESOSPHERE TEMPERATURE */
+  if (alt>zn2[mn2-1])
+    z=alt;
+  else
+    z=zn2[mn2-1];
+  mn=mn2;
+  z1=zn2[0];
+  z2=zn2[mn-1];
+  t1=tn2[0];
+  t2=tn2[mn-1];
+  zg = zeta(z, z1);
+  zgdif = zeta(z2, z1);
+
+  /* set up spline nodes */
+  for (k=0;k<mn;k++) {
+    xs[k]=zeta(zn2[k],z1)/zgdif;
+    ys[k]=1.0 / tn2[k];
+  }
+  yd1=-tgn2[0] / (t1*t1) * zgdif;
+  yd2=-tgn2[1] / (t2*t2) * zgdif * (pow(((re+z2)/(re+z1)),2.0));
+
+  /* calculate spline coefficients */
+  spline (xs, ys, mn, yd1, yd2, y2out);
+  x = zg/zgdif;
+  splint (xs, ys, y2out, mn, x, &y);
+
+  /* temperature at altitude */
+  *tz = 1.0 / y;
+  if (xm!=0.0) {
+    /* calaculate stratosphere / mesospehere density */
+    glb = gsurf / (pow((1.0 + z1/re),2.0));
+    gamm = xm * glb * zgdif / rgas;
+
+    /* Integrate temperature profile */
+    splini(xs, ys, y2out, mn, x, &yi);
+    expl=gamm*yi;
+    if (expl>50.0)
+      expl=50.0;
+
+    /* Density at altitude */
+    densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl);
+  }
+
+  if (alt>zn3[0]) {
+    if (xm==0.0)
+      return *tz;
+    else
+      return densm_tmp;
+  }
+
+  /* troposhere / stratosphere temperature */
+  z = alt;
+  mn = mn3;
+  z1=zn3[0];
+  z2=zn3[mn-1];
+  t1=tn3[0];
+  t2=tn3[mn-1];
+  zg=zeta(z,z1);
+  zgdif=zeta(z2,z1);
+
+  /* set up spline nodes */
+  for (k=0;k<mn;k++) {
+    xs[k] = zeta(zn3[k],z1) / zgdif;
+    ys[k] = 1.0 / tn3[k];
+  }
+  yd1=-tgn3[0] / (t1*t1) * zgdif;
+  yd2=-tgn3[1] / (t2*t2) * zgdif * (pow(((re+z2)/(re+z1)),2.0));
+
+  /* calculate spline coefficients */
+  spline (xs, ys, mn, yd1, yd2, y2out);
+  x = zg/zgdif;
+  splint (xs, ys, y2out, mn, x, &y);
+
+  /* temperature at altitude */
+  *tz = 1.0 / y;
+  if (xm!=0.0) {
+    /* calaculate tropospheric / stratosphere density */
+    glb = gsurf / (pow((1.0 + z1/re),2.0));
+    gamm = xm * glb * zgdif / rgas;
+
+    /* Integrate temperature profile */
+    splini(xs, ys, y2out, mn, x, &yi);
+    expl=gamm*yi;
+    if (expl>50.0)
+      expl=50.0;
+
+    /* Density at altitude */
+    densm_tmp = densm_tmp * (t1 / *tz) * exp(-expl);
+  }
+  if (xm==0.0)
+    return *tz;
+  else
+    return densm_tmp;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::densu(double alt, double dlb, double tinf, double tlb, double xm,
+                     double alpha, double *tz, double zlb, double s2, int mn1,
+                     double *zn1, double *tn1, double *tgn1)
+{
+/*      Calculate Temperature and Density Profiles for MSIS models
+ *      New lower thermo polynomial
+ */
+  double yd2, yd1, x=0.0, y=0.0;
+  double rgas=831.4;
+  double densu_temp=1.0;
+  double za, z, zg2, tt, ta=0.0;
+  double dta, z1=0.0, z2, t1=0.0, t2, zg, zgdif=0.0;
+  int mn=0;
+  int k;
+  double glb;
+  double expl;
+  double yi;
+  double densa;
+  double gamma, gamm;
+  double xs[5], ys[5], y2out[5];
+  /* joining altitudes of Bates and spline */
+  za=zn1[0];
+  if (alt>za)
+    z=alt;
+  else
+    z=za;
+
+  /* geopotential altitude difference from ZLB */
+  zg2 = zeta(z, zlb);
+
+  /* Bates temperature */
+  tt = tinf - (tinf - tlb) * exp(-s2*zg2);
+  ta = tt;
+  *tz = tt;
+  densu_temp = *tz;
+
+  if (alt<za) {
+    /* calculate temperature below ZA
+     * temperature gradient at ZA from Bates profile */
+    dta = (tinf - ta) * s2 * pow(((re+zlb)/(re+za)),2.0);
+    tgn1[0]=dta;
+    tn1[0]=ta;
+    if (alt>zn1[mn1-1])
+      z=alt;
+    else
+      z=zn1[mn1-1];
+    mn=mn1;
+    z1=zn1[0];
+    z2=zn1[mn-1];
+    t1=tn1[0];
+    t2=tn1[mn-1];
+    /* geopotental difference from z1 */
+    zg = zeta (z, z1);
+    zgdif = zeta(z2, z1);
+    /* set up spline nodes */
+    for (k=0;k<mn;k++) {
+      xs[k] = zeta(zn1[k], z1) / zgdif;
+      ys[k] = 1.0 / tn1[k];
+    }
+    /* end node derivatives */
+    yd1 = -tgn1[0] / (t1*t1) * zgdif;
+    yd2 = -tgn1[1] / (t2*t2) * zgdif * pow(((re+z2)/(re+z1)),2.0);
+    /* calculate spline coefficients */
+    spline (xs, ys, mn, yd1, yd2, y2out);
+    x = zg / zgdif;
+    splint (xs, ys, y2out, mn, x, &y);
+    /* temperature at altitude */
+    *tz = 1.0 / y;
+    densu_temp = *tz;
+  }
+  if (xm==0)
+    return densu_temp;
+
+  /* calculate density above za */
+  glb = gsurf / pow((1.0 + zlb/re),2.0);
+  gamma = xm * glb / (s2 * rgas * tinf);
+  expl = exp(-s2 * gamma * zg2);
+  if (expl>50.0)
+      expl=50.0;
+  if (tt<=0)
+    expl=50.0;
+
+  /* density at altitude */
+  densa = dlb * pow((tlb/tt),((1.0+alpha+gamma))) * expl;
+  densu_temp=densa;
+  if (alt>=za)
+    return densu_temp;
+
+  /* calculate density below za */
+  glb = gsurf / pow((1.0 + z1/re),2.0);
+  gamm = xm * glb * zgdif / rgas;
+
+  /* integrate spline temperatures */
+  splini (xs, ys, y2out, mn, x, &yi);
+  expl = gamm * yi;
+  if (expl>50.0)
+    expl=50.0;
+  if (*tz<=0)
+    expl=50.0;
+
+  /* density at altitude */
+  densu_temp = densu_temp * pow ((t1 / *tz),(1.0 + alpha)) * exp(-expl);
+  return densu_temp;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/*    3hr Magnetic activity functions */
+/*    Eq. A24d */
+double MSIS::g0(double a, double *p)
+{
+  return (a - 4.0 + (p[25] - 1.0) * (a - 4.0 + (exp(-sqrt(p[24]*p[24]) *
+                (a - 4.0)) - 1.0) / sqrt(p[24]*p[24])));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/*    Eq. A24c */
+double MSIS::sumex(double ex)
+{
+  return (1.0 + (1.0 - pow(ex,19.0)) / (1.0 - ex) * pow(ex,0.5));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/*    Eq. A24a */
+double MSIS::sg0(double ex, double *p, double *ap)
+{
+  return (g0(ap[1],p) + (g0(ap[2],p)*ex + g0(ap[3],p)*ex*ex +
+                g0(ap[4],p)*pow(ex,3.0)  + (g0(ap[5],p)*pow(ex,4.0) +
+                g0(ap[6],p)*pow(ex,12.0))*(1.0-pow(ex,8.0))/(1.0-ex)))/sumex(ex);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::globe7(double *p, struct nrlmsise_input *input,
+                      struct nrlmsise_flags *flags)
+{
+/*       CALCULATE G(L) FUNCTION
+ *       Upper Thermosphere Parameters */
+  double t[15];
+  int i,j;
+  int sw9=1;
+  double apd;
+  double xlong;
+  double tloc;
+  double c, s, c2, c4, s2;
+  double sr = 7.2722E-5;
+  double dgtr = 1.74533E-2;
+  double dr = 1.72142E-2;
+  double hr = 0.2618;
+  double cd32, cd18, cd14, cd39;
+  double p32, p18, p14, p39;
+  double df, dfa;
+  double f1, f2;
+  double tinf;
+  struct ap_array *ap;
+
+  tloc=input->lst;
+  for (j=0;j<14;j++)
+    t[j]=0;
+  if (flags->sw[9]>0)
+    sw9=1;
+  else if (flags->sw[9]<0)
+    sw9=-1;
+  xlong = input->g_long;
+
+  /* calculate legendre polynomials */
+  c = sin(input->g_lat * dgtr);
+  s = cos(input->g_lat * dgtr);
+  c2 = c*c;
+  c4 = c2*c2;
+  s2 = s*s;
+
+  plg[0][1] = c;
+  plg[0][2] = 0.5*(3.0*c2 -1.0);
+  plg[0][3] = 0.5*(5.0*c*c2-3.0*c);
+  plg[0][4] = (35.0*c4 - 30.0*c2 + 3.0)/8.0;
+  plg[0][5] = (63.0*c2*c2*c - 70.0*c2*c + 15.0*c)/8.0;
+  plg[0][6] = (11.0*c*plg[0][5] - 5.0*plg[0][4])/6.0;
+/*      plg[0][7] = (13.0*c*plg[0][6] - 6.0*plg[0][5])/7.0; */
+  plg[1][1] = s;
+  plg[1][2] = 3.0*c*s;
+  plg[1][3] = 1.5*(5.0*c2-1.0)*s;
+  plg[1][4] = 2.5*(7.0*c2*c-3.0*c)*s;
+  plg[1][5] = 1.875*(21.0*c4 - 14.0*c2 +1.0)*s;
+  plg[1][6] = (11.0*c*plg[1][5]-6.0*plg[1][4])/5.0;
+/*      plg[1][7] = (13.0*c*plg[1][6]-7.0*plg[1][5])/6.0; */
+/*      plg[1][8] = (15.0*c*plg[1][7]-8.0*plg[1][6])/7.0; */
+  plg[2][2] = 3.0*s2;
+  plg[2][3] = 15.0*s2*c;
+  plg[2][4] = 7.5*(7.0*c2 -1.0)*s2;
+  plg[2][5] = 3.0*c*plg[2][4]-2.0*plg[2][3];
+  plg[2][6] =(11.0*c*plg[2][5]-7.0*plg[2][4])/4.0;
+  plg[2][7] =(13.0*c*plg[2][6]-8.0*plg[2][5])/5.0;
+  plg[3][3] = 15.0*s2*s;
+  plg[3][4] = 105.0*s2*s*c;
+  plg[3][5] =(9.0*c*plg[3][4]-7.*plg[3][3])/2.0;
+  plg[3][6] =(11.0*c*plg[3][5]-8.*plg[3][4])/3.0;
+
+  if (!(((flags->sw[7]==0)&&(flags->sw[8]==0))&&(flags->sw[14]==0))) {
+    stloc = sin(hr*tloc);
+    ctloc = cos(hr*tloc);
+    s2tloc = sin(2.0*hr*tloc);
+    c2tloc = cos(2.0*hr*tloc);
+    s3tloc = sin(3.0*hr*tloc);
+    c3tloc = cos(3.0*hr*tloc);
+  }
+
+  cd32 = cos(dr*(input->doy-p[31]));
+  cd18 = cos(2.0*dr*(input->doy-p[17]));
+  cd14 = cos(dr*(input->doy-p[13]));
+  cd39 = cos(2.0*dr*(input->doy-p[38]));
+  p32=p[31];
+  p18=p[17];
+  p14=p[13];
+  p39=p[38];
+
+  /* F10.7 EFFECT */
+  df = input->f107 - input->f107A;
+  dfa = input->f107A - 150.0;
+  t[0] =  p[19]*df*(1.0+p[59]*dfa) + p[20]*df*df + p[21]*dfa + p[29]*pow(dfa,2.0);
+  f1 = 1.0 + (p[47]*dfa +p[19]*df+p[20]*df*df)*flags->swc[1];
+  f2 = 1.0 + (p[49]*dfa+p[19]*df+p[20]*df*df)*flags->swc[1];
+
+  /*  TIME INDEPENDENT */
+  t[1] = (p[1]*plg[0][2]+ p[2]*plg[0][4]+p[22]*plg[0][6]) +
+        (p[14]*plg[0][2])*dfa*flags->swc[1] +p[26]*plg[0][1];
+
+  /*  SYMMETRICAL ANNUAL */
+  t[2] = p[18]*cd32;
+
+  /*  SYMMETRICAL SEMIANNUAL */
+  t[3] = (p[15]+p[16]*plg[0][2])*cd18;
+
+  /*  ASYMMETRICAL ANNUAL */
+  t[4] =  f1*(p[9]*plg[0][1]+p[10]*plg[0][3])*cd14;
+
+  /*  ASYMMETRICAL SEMIANNUAL */
+  t[5] =    p[37]*plg[0][1]*cd39;
+
+        /* DIURNAL */
+  if (flags->sw[7]) {
+    double t71, t72;
+    t71 = (p[11]*plg[1][2])*cd14*flags->swc[5];
+    t72 = (p[12]*plg[1][2])*cd14*flags->swc[5];
+    t[6] = f2*((p[3]*plg[1][1] + p[4]*plg[1][3] + p[27]*plg[1][5] + t71) * \
+         ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + p[28]*plg[1][5] \
+            + t72)*stloc);
+}
+
+  /* SEMIDIURNAL */
+  if (flags->sw[8]) {
+    double t81, t82;
+    t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5];
+    t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5];
+    t[7] = f2*((p[5]*plg[2][2]+ p[41]*plg[2][4] + t81)*c2tloc +(p[8]*plg[2][2] + p[42]*plg[2][4] + t82)*s2tloc);
+  }
+
+  /* TERDIURNAL */
+  if (flags->sw[14]) {
+    t[13] = f2 * ((p[39]*plg[3][3]+(p[93]*plg[3][4]+p[46]*plg[3][6])*cd14*flags->swc[5])* s3tloc +(p[40]*plg[3][3]+(p[94]*plg[3][4]+p[48]*plg[3][6])*cd14*flags->swc[5])* c3tloc);
+}
+
+  /* magnetic activity based on daily ap */
+  if (flags->sw[9]==-1) {
+    ap = input->ap_a;
+    if (p[51]!=0) {
+      double exp1;
+      exp1 = exp(-10800.0*sqrt(p[51]*p[51])/(1.0+p[138]*(45.0-sqrt(input->g_lat*input->g_lat))));
+      if (exp1>0.99999)
+        exp1=0.99999;
+      if (p[24]<1.0E-4)
+        p[24]=1.0E-4;
+      apt[0]=sg0(exp1,p,ap->a);
+      /* apt[1]=sg2(exp1,p,ap->a);
+         apt[2]=sg0(exp2,p,ap->a);
+         apt[3]=sg2(exp2,p,ap->a);
+      */
+      if (flags->sw[9]) {
+        t[8] = apt[0]*(p[50]+p[96]*plg[0][2]+p[54]*plg[0][4]+ \
+     (p[125]*plg[0][1]+p[126]*plg[0][3]+p[127]*plg[0][5])*cd14*flags->swc[5]+ \
+     (p[128]*plg[1][1]+p[129]*plg[1][3]+p[130]*plg[1][5])*flags->swc[7]* \
+                 cos(hr*(tloc-p[131])));
+      }
+    }
+  } else {
+    double p44, p45;
+    apd=input->ap-4.0;
+    p44=p[43];
+    p45=p[44];
+    if (p44<0)
+      p44 = 1.0E-5;
+    apdf = apd + (p45-1.0)*(apd + (exp(-p44 * apd) - 1.0)/p44);
+    if (flags->sw[9]) {
+      t[8]=apdf*(p[32]+p[45]*plg[0][2]+p[34]*plg[0][4]+ \
+     (p[100]*plg[0][1]+p[101]*plg[0][3]+p[102]*plg[0][5])*cd14*flags->swc[5]+
+     (p[121]*plg[1][1]+p[122]*plg[1][3]+p[123]*plg[1][5])*flags->swc[7]*
+            cos(hr*(tloc-p[124])));
+    }
+  }
+
+  if ((flags->sw[10])&&(input->g_long>-1000.0)) {
+
+    /* longitudinal */
+    if (flags->sw[11]) {
+      t[10] = (1.0 + p[80]*dfa*flags->swc[1])* \
+     ((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\
+      +p[103]*plg[1][1]+p[104]*plg[1][3]+p[105]*plg[1][5]\
+      +flags->swc[5]*(p[109]*plg[1][1]+p[110]*plg[1][3]+p[111]*plg[1][5])*cd14)* \
+          cos(dgtr*input->g_long) \
+      +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\
+      +p[106]*plg[1][1]+p[107]*plg[1][3]+p[108]*plg[1][5]\
+      +flags->swc[5]*(p[112]*plg[1][1]+p[113]*plg[1][3]+p[114]*plg[1][5])*cd14)* \
+      sin(dgtr*input->g_long));
+    }
+
+    /* ut and mixed ut, longitude */
+    if (flags->sw[12]){
+      t[11]=(1.0+p[95]*plg[0][1])*(1.0+p[81]*dfa*flags->swc[1])*\
+        (1.0+p[119]*plg[0][1]*flags->swc[5]*cd14)*\
+        ((p[68]*plg[0][1]+p[69]*plg[0][3]+p[70]*plg[0][5])*\
+        cos(sr*(input->sec-p[71])));
+      t[11]+=flags->swc[11]*\
+        (p[76]*plg[2][3]+p[77]*plg[2][5]+p[78]*plg[2][7])*\
+        cos(sr*(input->sec-p[79])+2.0*dgtr*input->g_long)*(1.0+p[137]*dfa*flags->swc[1]);
+    }
+
+    /* ut, longitude magnetic activity */
+    if (flags->sw[13]) {
+      if (flags->sw[9]==-1) {
+        if (p[51]) {
+          t[12]=apt[0]*flags->swc[11]*(1.+p[132]*plg[0][1])*\
+            ((p[52]*plg[1][2]+p[98]*plg[1][4]+p[67]*plg[1][6])*\
+             cos(dgtr*(input->g_long-p[97])))\
+            +apt[0]*flags->swc[11]*flags->swc[5]*\
+            (p[133]*plg[1][1]+p[134]*plg[1][3]+p[135]*plg[1][5])*\
+            cd14*cos(dgtr*(input->g_long-p[136])) \
+            +apt[0]*flags->swc[12]* \
+            (p[55]*plg[0][1]+p[56]*plg[0][3]+p[57]*plg[0][5])*\
+            cos(sr*(input->sec-p[58]));
+        }
+      } else {
+        t[12] = apdf*flags->swc[11]*(1.0+p[120]*plg[0][1])*\
+          ((p[60]*plg[1][2]+p[61]*plg[1][4]+p[62]*plg[1][6])*\
+          cos(dgtr*(input->g_long-p[63])))\
+          +apdf*flags->swc[11]*flags->swc[5]* \
+          (p[115]*plg[1][1]+p[116]*plg[1][3]+p[117]*plg[1][5])* \
+          cd14*cos(dgtr*(input->g_long-p[118])) \
+          + apdf*flags->swc[12]* \
+          (p[83]*plg[0][1]+p[84]*plg[0][3]+p[85]*plg[0][5])* \
+          cos(sr*(input->sec-p[75]));
+      }
+    }
+  }
+
+  /* parms not used: 82, 89, 99, 139-149 */
+  tinf = p[30];
+  for (i=0;i<14;i++)
+    tinf = tinf + abs(flags->sw[i+1])*t[i];
+  return tinf;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double MSIS::glob7s(double *p, struct nrlmsise_input *input,
+                      struct nrlmsise_flags *flags)
+{
+/*    VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99
+ */
+  double pset=2.0;
+  double t[14];
+  double tt;
+  double cd32, cd18, cd14, cd39;
+  double p32, p18, p14, p39;
+  int i,j;
+  double dr=1.72142E-2;
+  double dgtr=1.74533E-2;
+  /* confirm parameter set */
+  if (p[99]==0)
+    p[99]=pset;
+  if (p[99]!=pset) {
+    printf("Wrong parameter set for glob7s\n");
+    return -1;
+  }
+  for (j=0;j<14;j++)
+    t[j]=0.0;
+  cd32 = cos(dr*(input->doy-p[31]));
+  cd18 = cos(2.0*dr*(input->doy-p[17]));
+  cd14 = cos(dr*(input->doy-p[13]));
+  cd39 = cos(2.0*dr*(input->doy-p[38]));
+  p32=p[31];
+  p18=p[17];
+  p14=p[13];
+  p39=p[38];
+
+  /* F10.7 */
+  t[0] = p[21]*dfa;
+
+  /* time independent */
+  t[1]=p[1]*plg[0][2] + p[2]*plg[0][4] + p[22]*plg[0][6] + p[26]*plg[0][1] + p[14]*plg[0][3] + p[59]*plg[0][5];
+
+        /* SYMMETRICAL ANNUAL */
+  t[2]=(p[18]+p[47]*plg[0][2]+p[29]*plg[0][4])*cd32;
+
+        /* SYMMETRICAL SEMIANNUAL */
+  t[3]=(p[15]+p[16]*plg[0][2]+p[30]*plg[0][4])*cd18;
+
+        /* ASYMMETRICAL ANNUAL */
+  t[4]=(p[9]*plg[0][1]+p[10]*plg[0][3]+p[20]*plg[0][5])*cd14;
+
+  /* ASYMMETRICAL SEMIANNUAL */
+  t[5]=(p[37]*plg[0][1])*cd39;
+
+        /* DIURNAL */
+  if (flags->sw[7]) {
+    double t71, t72;
+    t71 = p[11]*plg[1][2]*cd14*flags->swc[5];
+    t72 = p[12]*plg[1][2]*cd14*flags->swc[5];
+    t[6] = ((p[3]*plg[1][1] + p[4]*plg[1][3] + t71) * ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + t72) * stloc) ;
+  }
+
+  /* SEMIDIURNAL */
+  if (flags->sw[8]) {
+    double t81, t82;
+    t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags->swc[5];
+    t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags->swc[5];
+    t[7] = ((p[5]*plg[2][2] + p[41]*plg[2][4] + t81) * c2tloc + (p[8]*plg[2][2] + p[42]*plg[2][4] + t82) * s2tloc);
+  }
+
+  /* TERDIURNAL */
+  if (flags->sw[14]) {
+    t[13] = p[39] * plg[3][3] * s3tloc + p[40] * plg[3][3] * c3tloc;
+  }
+
+  /* MAGNETIC ACTIVITY */
+  if (flags->sw[9]) {
+    if (flags->sw[9]==1)
+      t[8] = apdf * (p[32] + p[45] * plg[0][2] * flags->swc[2]);
+    if (flags->sw[9]==-1)
+      t[8]=(p[50]*apt[0] + p[96]*plg[0][2] * apt[0]*flags->swc[2]);
+  }
+
+  /* LONGITUDINAL */
+  if (!((flags->sw[10]==0) || (flags->sw[11]==0) || (input->g_long<=-1000.0))) {
+    t[10] = (1.0 + plg[0][1]*(p[80]*flags->swc[5]*cos(dr*(input->doy-p[81]))\
+            +p[85]*flags->swc[6]*cos(2.0*dr*(input->doy-p[86])))\
+      +p[83]*flags->swc[3]*cos(dr*(input->doy-p[84]))\
+      +p[87]*flags->swc[4]*cos(2.0*dr*(input->doy-p[88])))\
+      *((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\
+      +p[74]*plg[1][1]+p[75]*plg[1][3]+p[76]*plg[1][5]\
+      )*cos(dgtr*input->g_long)\
+      +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\
+      +p[77]*plg[1][1]+p[78]*plg[1][3]+p[79]*plg[1][5]\
+      )*sin(dgtr*input->g_long));
+  }
+  tt=0;
+  for (i=0;i<14;i++)
+    tt+=abs(flags->sw[i+1])*t[i];
+  return tt;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::gtd7(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
+                  struct nrlmsise_output *output)
+{
+  double xlat;
+  double xmm;
+  int mn3 = 5;
+  double zn3[5]={32.5,20.0,15.0,10.0,0.0};
+  int mn2 = 4;
+  double zn2[4]={72.5,55.0,45.0,32.5};
+  double altt;
+  double zmix=62.5;
+  double tmp;
+  double dm28m;
+  double tz;
+  double dmc;
+  double dmr;
+  double dz28;
+  struct nrlmsise_output soutput;
+  int i;
+
+  tselec(flags);
+
+  /* Latitude variation of gravity (none for sw[2]=0) */
+  xlat=input->g_lat;
+  if (flags->sw[2]==0)
+    xlat=45.0;
+  glatf(xlat, &gsurf, &re);
+
+  xmm = pdm[2][4];
+
+  /* THERMOSPHERE / MESOSPHERE (above zn2[0]) */
+  if (input->alt>zn2[0])
+    altt=input->alt;
+  else
+    altt=zn2[0];
+
+  tmp=input->alt;
+  input->alt=altt;
+  gts7(input, flags, &soutput);
+  altt=input->alt;
+  input->alt=tmp;
+  if (flags->sw[0])   /* metric adjustment */
+    dm28m=dm28*1.0E6;
+  else
+    dm28m=dm28;
+  output->t[0]=soutput.t[0];
+  output->t[1]=soutput.t[1];
+  if (input->alt>=zn2[0]) {
+    for (i=0;i<9;i++)
+      output->d[i]=soutput.d[i];
+    return;
+  }
+
+/*       LOWER MESOSPHERE/UPPER STRATOSPHERE (between zn3[0] and zn2[0])
+ *         Temperature at nodes and gradients at end nodes
+ *         Inverse temperature a linear function of spherical harmonics
+ */
+  meso_tgn2[0]=meso_tgn1[1];
+  meso_tn2[0]=meso_tn1[4];
+        meso_tn2[1]=pma[0][0]*pavgm[0]/(1.0-flags->sw[20]*glob7s(pma[0], input, flags));
+        meso_tn2[2]=pma[1][0]*pavgm[1]/(1.0-flags->sw[20]*glob7s(pma[1], input, flags));
+        meso_tn2[3]=pma[2][0]*pavgm[2]/(1.0-flags->sw[20]*flags->sw[22]*glob7s(pma[2], input, flags));
+  meso_tgn2[1]=pavgm[8]*pma[9][0]*(1.0+flags->sw[20]*flags->sw[22]*glob7s(pma[9], input, flags))*meso_tn2[3]*meso_tn2[3]/(pow((pma[2][0]*pavgm[2]),2.0));
+  meso_tn3[0]=meso_tn2[3];
+
+  if (input->alt<zn3[0]) {
+/*       LOWER STRATOSPHERE AND TROPOSPHERE (below zn3[0])
+ *         Temperature at nodes and gradients at end nodes
+ *         Inverse temperature a linear function of spherical harmonics
+ */
+    meso_tgn3[0]=meso_tgn2[1];
+    meso_tn3[1]=pma[3][0]*pavgm[3]/(1.0-flags->sw[22]*glob7s(pma[3], input, flags));
+    meso_tn3[2]=pma[4][0]*pavgm[4]/(1.0-flags->sw[22]*glob7s(pma[4], input, flags));
+    meso_tn3[3]=pma[5][0]*pavgm[5]/(1.0-flags->sw[22]*glob7s(pma[5], input, flags));
+    meso_tn3[4]=pma[6][0]*pavgm[6]/(1.0-flags->sw[22]*glob7s(pma[6], input, flags));
+    meso_tgn3[1]=pma[7][0]*pavgm[7]*(1.0+flags->sw[22]*glob7s(pma[7], input, flags)) *meso_tn3[4]*meso_tn3[4]/(pow((pma[6][0]*pavgm[6]),2.0));
+  }
+
+        /* LINEAR TRANSITION TO FULL MIXING BELOW zn2[0] */
+
+  dmc=0;
+  if (input->alt>zmix)
+    dmc = 1.0 - (zn2[0]-input->alt)/(zn2[0] - zmix);
+  dz28=soutput.d[2];
+
+  /**** N2 density ****/
+  dmr=soutput.d[2] / dm28m - 1.0;
+  output->d[2]=densm(input->alt,dm28m,xmm, &tz, mn3, zn3, meso_tn3, meso_tgn3, mn2, zn2, meso_tn2, meso_tgn2);
+  output->d[2]=output->d[2] * (1.0 + dmr*dmc);
+
+  /**** HE density ****/
+  dmr = soutput.d[0] / (dz28 * pdm[0][1]) - 1.0;
+  output->d[0] = output->d[2] * pdm[0][1] * (1.0 + dmr*dmc);
+
+  /**** O density ****/
+  output->d[1] = 0;
+  output->d[8] = 0;
+
+  /**** O2 density ****/
+  dmr = soutput.d[3] / (dz28 * pdm[3][1]) - 1.0;
+  output->d[3] = output->d[2] * pdm[3][1] * (1.0 + dmr*dmc);
+
+  /**** AR density ***/
+  dmr = soutput.d[4] / (dz28 * pdm[4][1]) - 1.0;
+  output->d[4] = output->d[2] * pdm[4][1] * (1.0 + dmr*dmc);
+
+  /**** Hydrogen density ****/
+  output->d[6] = 0;
+
+  /**** Atomic nitrogen density ****/
+  output->d[7] = 0;
+
+  /**** Total mass density */
+  output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] +
+                     28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4]
+                     + output->d[6] + 14.0 * output->d[7]);
+
+  if (flags->sw[0])
+    output->d[5]=output->d[5]/1000;
+
+  /**** temperature at altitude ****/
+  dd = densm(input->alt, 1.0, 0, &tz, mn3, zn3, meso_tn3, meso_tgn3,
+                   mn2, zn2, meso_tn2, meso_tgn2);
+  output->t[1]=tz;
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::gtd7d(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
+                   struct nrlmsise_output *output)
+{
+  gtd7(input, flags, output);
+  output->d[5] = 1.66E-24 * (4.0 * output->d[0] + 16.0 * output->d[1] +
+                   28.0 * output->d[2] + 32.0 * output->d[3] + 40.0 * output->d[4]
+                   + output->d[6] + 14.0 * output->d[7] + 16.0 * output->d[8]);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::ghp7(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
+                  struct nrlmsise_output *output, double press)
+{
+  double bm = 1.3806E-19;
+  double rgas = 831.4;
+  double test = 0.00043;
+  double ltest = 12;
+  double pl, p;
+  double zi = 0.0;
+  double z;
+  double cl, cl2;
+  double ca, cd;
+  double xn, xm, diff;
+  double g, sh;
+  int l;
+  pl = log10(press);
+  if (pl >= -5.0) {
+    if (pl>2.5)
+      zi = 18.06 * (3.00 - pl);
+    else if ((pl>0.075) && (pl<=2.5))
+      zi = 14.98 * (3.08 - pl);
+    else if ((pl>-1) && (pl<=0.075))
+      zi = 17.80 * (2.72 - pl);
+    else if ((pl>-2) && (pl<=-1))
+      zi = 14.28 * (3.64 - pl);
+    else if ((pl>-4) && (pl<=-2))
+      zi = 12.72 * (4.32 -pl);
+    else if (pl<=-4)
+      zi = 25.3 * (0.11 - pl);
+    cl = input->g_lat/90.0;
+    cl2 = cl*cl;
+    if (input->doy<182)
+      cd = (1.0 - (double) input->doy) / 91.25;
+    else
+      cd = ((double) input->doy) / 91.25 - 3.0;
+    ca = 0;
+    if ((pl > -1.11) && (pl<=-0.23))
+      ca = 1.0;
+    if (pl > -0.23)
+      ca = (2.79 - pl) / (2.79 + 0.23);
+    if ((pl <= -1.11) && (pl>-3))
+      ca = (-2.93 - pl)/(-2.93 + 1.11);
+    z = zi - 4.87 * cl * cd * ca - 1.64 * cl2 * ca + 0.31 * ca * cl;
+  } else
+    z = 22.0 * pow((pl + 4.0),2.0) + 110.0;
+
+  /* iteration  loop */
+  l = 0;
+  do {
+    l++;
+    input->alt = z;
+    gtd7(input, flags, output);
+    z = input->alt;
+    xn = output->d[0] + output->d[1] + output->d[2] + output->d[3] + output->d[4] + output->d[6] + output->d[7];
+    p = bm * xn * output->t[1];
+    if (flags->sw[0])
+      p = p*1.0E-6;
+    diff = pl - log10(p);
+    if (sqrt(diff*diff)<test)
+      return;
+    if (l==ltest) {
+      printf("ERROR: ghp7 not converging for press %e, diff %e",press,diff);
+      return;
+    }
+    xm = output->d[5] / xn / 1.66E-24;
+    if (flags->sw[0])
+      xm = xm * 1.0E3;
+    g = gsurf / (pow((1.0 + z/re),2.0));
+    sh = rgas * output->t[1] / (xm * g);
+
+    /* new altitude estimate using scale height */
+    if (l <  6)
+      z = z - sh * diff * 2.302;
+    else
+      z = z - sh * diff;
+  } while (1==1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void MSIS::gts7(struct nrlmsise_input *input, struct nrlmsise_flags *flags,
+                  struct nrlmsise_output *output)
+{
+/*     Thermospheric portion of NRLMSISE-00
+ *     See GTD7 for more extensive comments
+ *     alt > 72.5 km!
+ */
+  double za;
+  int i, j;
+  double ddum, z;
+  double zn1[5] = {120.0, 110.0, 100.0, 90.0, 72.5};
+  double tinf;
+  int mn1 = 5;
+  double g0;
+  double tlb;
+  double s, z0, t0, tr12;
+  double db01, db04, db14, db16, db28, db32, db40, db48;
+  double zh28, zh04, zh16, zh32, zh40, zh01, zh14;
+  double zhm28, zhm04, zhm16, zhm32, zhm40, zhm01, zhm14;
+  double xmd;
+  double b28, b04, b16, b32, b40, b01, b14;
+  double tz;
+  double g28, g4, g16, g32, g40, g1, g14;
+  double zhf, xmm;
+  double zc04, zc16, zc32, zc40, zc01, zc14;
+  double hc04, hc16, hc32, hc40, hc01, hc14;
+  double hcc16, hcc32, hcc01, hcc14;
+  double zcc16, zcc32, zcc01, zcc14;
+  double rc16, rc32, rc01, rc14;
+  double rl;
+  double g16h, db16h, tho, zsht, zmho, zsho;
+  double dgtr=1.74533E-2;
+  double dr=1.72142E-2;
+  double alpha[9]={-0.38, 0.0, 0.0, 0.0, 0.17, 0.0, -0.38, 0.0, 0.0};
+  double altl[8]={200.0, 300.0, 160.0, 250.0, 240.0, 450.0, 320.0, 450.0};
+  double dd;
+  double hc216, hcc232;
+  za = pdl[1][15];
+  zn1[0] = za;
+  for (j=0;j<9;j++)
+    output->d[j]=0;
+
+  /* TINF VARIATIONS NOT IMPORTANT BELOW ZA OR ZN1(1) */
+  if (input->alt>zn1[0])
+    tinf = ptm[0]*pt[0] * \
+      (1.0+flags->sw[16]*globe7(pt,input,flags));
+  else
+    tinf = ptm[0]*pt[0];
+  output->t[0]=tinf;
+
+  /*  GRADIENT VARIATIONS NOT IMPORTANT BELOW ZN1(5) */
+  if (input->alt>zn1[4])
+    g0 = ptm[3]*ps[0] * \
+      (1.0+flags->sw[19]*globe7(ps,input,flags));
+  else
+    g0 = ptm[3]*ps[0];
+  tlb = ptm[1] * (1.0 + flags->sw[17]*globe7(pd[3],input,flags))*pd[3][0];
+  s = g0 / (tinf - tlb);
+
+/*      Lower thermosphere temp variations not significant for
+ *       density above 300 km */
+  if (input->alt<300.0) {
+    meso_tn1[1]=ptm[6]*ptl[0][0]/(1.0-flags->sw[18]*glob7s(ptl[0], input, flags));
+    meso_tn1[2]=ptm[2]*ptl[1][0]/(1.0-flags->sw[18]*glob7s(ptl[1], input, flags));
+    meso_tn1[3]=ptm[7]*ptl[2][0]/(1.0-flags->sw[18]*glob7s(ptl[2], input, flags));
+    meso_tn1[4]=ptm[4]*ptl[3][0]/(1.0-flags->sw[18]*flags->sw[20]*glob7s(ptl[3], input, flags));
+    meso_tgn1[1]=ptm[8]*pma[8][0]*(1.0+flags->sw[18]*flags->sw[20]*glob7s(pma[8], input, flags))*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0));
+  } else {
+    meso_tn1[1]=ptm[6]*ptl[0][0];
+    meso_tn1[2]=ptm[2]*ptl[1][0];
+    meso_tn1[3]=ptm[7]*ptl[2][0];
+    meso_tn1[4]=ptm[4]*ptl[3][0];
+    meso_tgn1[1]=ptm[8]*pma[8][0]*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0));
+  }
+
+  z0 = zn1[3];
+  t0 = meso_tn1[3];
+  tr12 = 1.0;
+
+  /* N2 variation factor at Zlb */
+  g28=flags->sw[21]*globe7(pd[2], input, flags);
+
+  /* VARIATION OF TURBOPAUSE HEIGHT */
+  zhf=pdl[1][24]*(1.0+flags->sw[5]*pdl[0][24]*sin(dgtr*input->g_lat)*cos(dr*(input->doy-pt[13])));
+  output->t[0]=tinf;
+  xmm = pdm[2][4];
+  z = input->alt;
+
+
+        /**** N2 DENSITY ****/
+
+  /* Diffusive density at Zlb */
+  db28 = pdm[2][0]*exp(g28)*pd[2][0];
+  /* Diffusive density at Alt */
+  output->d[2]=densu(z,db28,tinf,tlb,28.0,alpha[2],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+  dd=output->d[2];
+  /* Turbopause */
+  zh28=pdm[2][2]*zhf;
+  zhm28=pdm[2][3]*pdl[1][5];
+  xmd=28.0-xmm;
+  /* Mixed density at Zlb */
+  b28=densu(zh28,db28,tinf,tlb,xmd,(alpha[2]-1.0),&tz,ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1);
+  if ((flags->sw[15])&&(z<=altl[2])) {
+    /*  Mixed density at Alt */
+    dm28=densu(z,b28,tinf,tlb,xmm,alpha[2],&tz,ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    /*  Net density at Alt */
+    output->d[2]=dnet(output->d[2],dm28,zhm28,xmm,28.0);
+  }
+
+
+        /**** HE DENSITY ****/
+
+  /*   Density variation factor at Zlb */
+  g4 = flags->sw[21]*globe7(pd[0], input, flags);
+  /*  Diffusive density at Zlb */
+  db04 = pdm[0][0]*exp(g4)*pd[0][0];
+        /*  Diffusive density at Alt */
+  output->d[0]=densu(z,db04,tinf,tlb, 4.,alpha[0],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+  dd=output->d[0];
+  if ((flags->sw[15]) && (z<altl[0])) {
+    /*  Turbopause */
+    zh04=pdm[0][2];
+    /*  Mixed density at Zlb */
+    b04=densu(zh04,db04,tinf,tlb,4.-xmm,alpha[0]-1.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    /*  Mixed density at Alt */
+    dm04=densu(z,b04,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    zhm04=zhm28;
+    /*  Net density at Alt */
+    output->d[0]=dnet(output->d[0],dm04,zhm04,xmm,4.);
+    /*  Correction to specified mixing ratio at ground */
+    rl=log(b28*pdm[0][1]/b04);
+    zc04=pdm[0][4]*pdl[1][0];
+    hc04=pdm[0][5]*pdl[1][1];
+    /*  Net density corrected at Alt */
+    output->d[0]=output->d[0]*ccor(z,rl,hc04,zc04);
+  }
+
+
+        /**** O DENSITY ****/
+
+  /*  Density variation factor at Zlb */
+  g16= flags->sw[21]*globe7(pd[1],input,flags);
+  /*  Diffusive density at Zlb */
+  db16 =  pdm[1][0]*exp(g16)*pd[1][0];
+        /*   Diffusive density at Alt */
+  output->d[1]=densu(z,db16,tinf,tlb, 16.,alpha[1],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1);
+  dd=output->d[1];
+  if ((flags->sw[15]) && (z<=altl[1])) {
+    /*   Turbopause */
+    zh16=pdm[1][2];
+    /*  Mixed density at Zlb */
+    b16=densu(zh16,db16,tinf,tlb,16.0-xmm,(alpha[1]-1.0), &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    /*  Mixed density at Alt */
+    dm16=densu(z,b16,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    zhm16=zhm28;
+    /*  Net density at Alt */
+    output->d[1]=dnet(output->d[1],dm16,zhm16,xmm,16.);
+    rl=pdm[1][1]*pdl[1][16]*(1.0+flags->sw[1]*pdl[0][23]*(input->f107A-150.0));
+    hc16=pdm[1][5]*pdl[1][3];
+    zc16=pdm[1][4]*pdl[1][2];
+    hc216=pdm[1][5]*pdl[1][4];
+    output->d[1]=output->d[1]*ccor2(z,rl,hc16,zc16,hc216);
+    /*   Chemistry correction */
+    hcc16=pdm[1][7]*pdl[1][13];
+    zcc16=pdm[1][6]*pdl[1][12];
+    rc16=pdm[1][3]*pdl[1][14];
+    /*  Net density corrected at Alt */
+    output->d[1]=output->d[1]*ccor(z,rc16,hcc16,zcc16);
+  }
+
+
+        /**** O2 DENSITY ****/
+
+        /*   Density variation factor at Zlb */
+  g32= flags->sw[21]*globe7(pd[4], input, flags);
+        /*  Diffusive density at Zlb */
+  db32 = pdm[3][0]*exp(g32)*pd[4][0];
+        /*   Diffusive density at Alt */
+  output->d[3]=densu(z,db32,tinf,tlb, 32.,alpha[3],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1);
+  dd=output->d[3];
+  if (flags->sw[15]) {
+    if (z<=altl[3]) {
+      /*   Turbopause */
+      zh32=pdm[3][2];
+      /*  Mixed density at Zlb */
+      b32=densu(zh32,db32,tinf,tlb,32.-xmm,alpha[3]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+      /*  Mixed density at Alt */
+      dm32=densu(z,b32,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+      zhm32=zhm28;
+      /*  Net density at Alt */
+      output->d[3]=dnet(output->d[3],dm32,zhm32,xmm,32.);
+      /*   Correction to specified mixing ratio at ground */
+      rl=log(b28*pdm[3][1]/b32);
+      hc32=pdm[3][5]*pdl[1][7];
+      zc32=pdm[3][4]*pdl[1][6];
+      output->d[3]=output->d[3]*ccor(z,rl,hc32,zc32);
+    }
+    /*  Correction for general departure from diffusive equilibrium above Zlb */
+    hcc32=pdm[3][7]*pdl[1][22];
+    hcc232=pdm[3][7]*pdl[0][22];
+    zcc32=pdm[3][6]*pdl[1][21];
+    rc32=pdm[3][3]*pdl[1][23]*(1.+flags->sw[1]*pdl[0][23]*(input->f107A-150.));
+    /*  Net density corrected at Alt */
+    output->d[3]=output->d[3]*ccor2(z,rc32,hcc32,zcc32,hcc232);
+  }
+
+
+        /**** AR DENSITY ****/
+
+        /*   Density variation factor at Zlb */
+  g40= flags->sw[20]*globe7(pd[5],input,flags);
+        /*  Diffusive density at Zlb */
+  db40 = pdm[4][0]*exp(g40)*pd[5][0];
+  /*   Diffusive density at Alt */
+  output->d[4]=densu(z,db40,tinf,tlb, 40.,alpha[4],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+  dd=output->d[4];
+  if ((flags->sw[15]) && (z<=altl[4])) {
+    /*   Turbopause */
+    zh40=pdm[4][2];
+    /*  Mixed density at Zlb */
+    b40=densu(zh40,db40,tinf,tlb,40.-xmm,alpha[4]-1.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    /*  Mixed density at Alt */
+    dm40=densu(z,b40,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    zhm40=zhm28;
+    /*  Net density at Alt */
+    output->d[4]=dnet(output->d[4],dm40,zhm40,xmm,40.);
+    /*   Correction to specified mixing ratio at ground */
+    rl=log(b28*pdm[4][1]/b40);
+    hc40=pdm[4][5]*pdl[1][9];
+    zc40=pdm[4][4]*pdl[1][8];
+    /*  Net density corrected at Alt */
+    output->d[4]=output->d[4]*ccor(z,rl,hc40,zc40);
+    }
+
+
+        /**** HYDROGEN DENSITY ****/
+
+        /*   Density variation factor at Zlb */
+  g1 = flags->sw[21]*globe7(pd[6], input, flags);
+        /*  Diffusive density at Zlb */
+  db01 = pdm[5][0]*exp(g1)*pd[6][0];
+        /*   Diffusive density at Alt */
+  output->d[6]=densu(z,db01,tinf,tlb,1.,alpha[6],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+  dd=output->d[6];
+  if ((flags->sw[15]) && (z<=altl[6])) {
+    /*   Turbopause */
+    zh01=pdm[5][2];
+    /*  Mixed density at Zlb */
+    b01=densu(zh01,db01,tinf,tlb,1.-xmm,alpha[6]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    /*  Mixed density at Alt */
+    dm01=densu(z,b01,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    zhm01=zhm28;
+    /*  Net density at Alt */
+    output->d[6]=dnet(output->d[6],dm01,zhm01,xmm,1.);
+    /*   Correction to specified mixing ratio at ground */
+    rl=log(b28*pdm[5][1]*sqrt(pdl[1][17]*pdl[1][17])/b01);
+    hc01=pdm[5][5]*pdl[1][11];
+    zc01=pdm[5][4]*pdl[1][10];
+    output->d[6]=output->d[6]*ccor(z,rl,hc01,zc01);
+    /*   Chemistry correction */
+    hcc01=pdm[5][7]*pdl[1][19];
+    zcc01=pdm[5][6]*pdl[1][18];
+    rc01=pdm[5][3]*pdl[1][20];
+    /*  Net density corrected at Alt */
+    output->d[6]=output->d[6]*ccor(z,rc01,hcc01,zcc01);
+}
+
+
+        /**** ATOMIC NITROGEN DENSITY ****/
+
+  /*   Density variation factor at Zlb */
+  g14 = flags->sw[21]*globe7(pd[7],input,flags);
+        /*  Diffusive density at Zlb */
+  db14 = pdm[6][0]*exp(g14)*pd[7][0];
+        /*   Diffusive density at Alt */
+  output->d[7]=densu(z,db14,tinf,tlb,14.,alpha[7],&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+  dd=output->d[7];
+  if ((flags->sw[15]) && (z<=altl[7])) {
+    /*   Turbopause */
+    zh14=pdm[6][2];
+    /*  Mixed density at Zlb */
+    b14=densu(zh14,db14,tinf,tlb,14.-xmm,alpha[7]-1., &output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    /*  Mixed density at Alt */
+    dm14=densu(z,b14,tinf,tlb,xmm,0.,&output->t[1],ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1);
+    zhm14=zhm28;
+    /*  Net density at Alt */
+    output->d[7]=dnet(output->d[7],dm14,zhm14,xmm,14.);
+    /*   Correction to specified mixing ratio at ground */
+    rl=log(b28*pdm[6][1]*sqrt(pdl[0][2]*pdl[0][2])/b14);
+    hc14=pdm[6][5]*pdl[0][1];
+    zc14=pdm[6][4]*pdl[0][0];
+    output->d[7]=output->d[7]*ccor(z,rl,hc14,zc14);
+    /*   Chemistry correction */
+    hcc14=pdm[6][7]*pdl[0][4];
+    zcc14=pdm[6][6]*pdl[0][3];
+    rc14=pdm[6][3]*pdl[0][5];
+    /*  Net density corrected at Alt */
+    output->d[7]=output->d[7]*ccor(z,rc14,hcc14,zcc14);
+  }
+
+
+        /**** Anomalous OXYGEN DENSITY ****/
+
+  g16h = flags->sw[21]*globe7(pd[8],input,flags);
+  db16h = pdm[7][0]*exp(g16h)*pd[8][0];
+  tho = pdm[7][9]*pdl[0][6];
+  dd=densu(z,db16h,tho,tho,16.,alpha[8],&output->t[1],ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1);
+  zsht=pdm[7][5];
+  zmho=pdm[7][4];
+  zsho=scalh(zmho,16.0,tho);
+  output->d[8]=dd*exp(-zsht/zsho*(exp(-(z-zmho)/zsht)-1.));
+
+
+  /* total mass density */
+  output->d[5] = 1.66E-24*(4.0*output->d[0]+16.0*output->d[1]+28.0*output->d[2]+32.0*output->d[3]+40.0*output->d[4]+ output->d[6]+14.0*output->d[7]);
+  db48=1.66E-24*(4.0*db04+16.0*db16+28.0*db28+32.0*db32+40.0*db40+db01+14.0*db14);
+
+
+
+  /* temperature */
+  z = sqrt(input->alt*input->alt);
+  ddum = densu(z,1.0, tinf, tlb, 0.0, 0.0, &output->t[1], ptm[5], s, mn1, zn1, meso_tn1, meso_tgn1);
+  if (flags->sw[0]) {
+    for(i=0;i<9;i++)
+      output->d[i]=output->d[i]*1.0E6;
+    output->d[5]=output->d[5]/1000;
+  }
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 MSIS::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: MSIS" << endl;
+    if (from == 1) cout << "Destroyed:    MSIS" << 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 & 32) { // Turbulence
+    if (frame == 0 && from == 2) {
+      cout << "vTurbulence(X), vTurbulence(Y), vTurbulence(Z), "
+           << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), "
+           << "vDirection(X), vDirection(Y), vDirection(Z), "
+           << "Magnitude, "
+           << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl;
+    } else if (from == 2) {
+      cout << vTurbulence << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl;
+    }
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+
+
+
+} // namespace JSBSim
+
diff --git a/src/FDM/JSBSim/models/atmosphere/FGMSIS.h b/src/FDM/JSBSim/models/atmosphere/FGMSIS.h
new file mode 100755 (executable)
index 0000000..8f2b652
--- /dev/null
@@ -0,0 +1,209 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGMSIS.h
+ Description:  MSIS-00 Atmosphere
+ Author:       David Culp
+ Date started: 12/14/03
+ ------------- Copyright (C) 2003  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
+--------------------------------------------------------------------------------
+12/14/03   DPC   Created
+01/11/04   DPC   Derive from FGAtmosphere
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGMSIS_H
+#define FGMSIS_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <models/FGAtmosphere.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_MSIS "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models the MSIS-00 atmosphere.
+    This is a wrapper for the NRL-MSIS-00 model 2001:
+
+    This C++ format model wraps the NRLMSISE-00 C source code package - release
+    20020503
+    The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and
+    Doug Drob. They also wrote a NRLMSISE-00 distribution package in 
+    FORTRAN which is available at
+    http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm
+    Dominik Brodowski implemented and maintains this C version. You can
+    reach him at devel@brodo.de. See the file "DOCUMENTATION" for details,
+    and check http://www.brodo.de/english/pub/nrlmsise/index.html for
+    updated releases of this package.
+    @author David Culp
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+STRUCT DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+struct nrlmsise_flags {
+  int switches[24];
+  double sw[24];
+  double swc[24];
+};
+
+struct ap_array {
+  double a[7];   
+};
+
+struct nrlmsise_input {
+  int year;      /* year, currently ignored                           */
+  int doy;       /* day of year                                       */
+  double sec;    /* seconds in day (UT)                               */
+  double alt;    /* altitude in kilometers                            */
+  double g_lat;  /* geodetic latitude                                 */
+  double g_long; /* geodetic longitude                                */
+  double lst;    /* local apparent solar time (hours), see note below */
+  double f107A;  /* 81 day average of F10.7 flux (centered on DOY)    */
+  double f107;   /* daily F10.7 flux for previous day                 */
+  double ap;     /* magnetic index(daily)                             */
+  struct ap_array *ap_a; /* see above */
+};
+
+struct nrlmsise_output {
+  double d[9];   /* densities    */
+  double t[2];   /* temperatures */
+};
+
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class MSIS : public FGAtmosphere
+{
+public:
+
+  /// Constructor
+  MSIS(FGFDMExec*);
+  /// Destructor
+  ~MSIS();
+  /** Runs the MSIS-00 atmosphere model; called by the Executive
+      @return false if no error */
+  bool Run(void);
+
+  bool InitModel(void);
+
+  /// Does nothing. External control is not allowed.
+  void UseExternal(void);
+
+private:
+
+  void Calculate(int day,      // day of year (1 to 366) 
+                 double sec,   // seconds in day (0.0 to 86400.0)
+                 double alt,   // altitude, feet
+                 double lat,   // geodetic latitude, degrees
+                 double lon    // geodetic longitude, degrees
+                );
+
+  void Debug(int from);
+
+  nrlmsise_flags flags;
+  nrlmsise_input input;
+  nrlmsise_output output;
+  ap_array aph;
+
+  /* PARMB */
+  double gsurf;
+  double re;
+
+  /* GTS3C */
+  double dd;
+
+  /* DMIX */
+  double dm04, dm16, dm28, dm32, dm40, dm01, dm14;
+
+  /* MESO7 */
+  double meso_tn1[5];
+  double meso_tn2[4];
+  double meso_tn3[3];
+  double meso_tgn1[2];
+  double meso_tgn2[2];
+  double meso_tgn3[2];
+
+  /* LPOLY */
+  double dfa;
+  double plg[4][9];
+  double ctloc, stloc;
+  double c2tloc, s2tloc;
+  double s3tloc, c3tloc;
+  double apdf, apt[4];
+
+  void tselec(struct nrlmsise_flags *flags);
+  void glatf(double lat, double *gv, double *reff);
+  double ccor(double alt, double r, double h1, double zh);
+  double ccor2(double alt, double r, double h1, double zh, double h2);
+  double scalh(double alt, double xm, double temp);
+  double dnet(double dd, double dm, double zhm, double xmm, double xm);
+  void splini(double *xa, double *ya, double *y2a, int n, double x, double *y);
+  void splint(double *xa, double *ya, double *y2a, int n, double x, double *y);
+  void spline(double *x, double *y, int n, double yp1, double ypn, double *y2);
+  double zeta(double zz, double zl);
+  double densm(double alt, double d0, double xm, double *tz, int mn3, double *zn3,
+               double *tn3, double *tgn3, int mn2, double *zn2, double *tn2,
+               double *tgn2);
+  double densu(double alt, double dlb, double tinf, double tlb, double xm, 
+               double alpha, double *tz, double zlb, double s2, int mn1, 
+               double *zn1, double *tn1, double *tgn1);
+  double g0(double a, double *p);
+  double sumex(double ex);
+  double sg0(double ex, double *p, double *ap);
+  double globe7(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
+  double glob7s(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
+  void gtd7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
+  void gtd7d(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); 
+  void ghp7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output, double press);
+  void gts7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); 
+
+};
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/atmosphere/FGMSISData.cpp b/src/FDM/JSBSim/models/atmosphere/FGMSISData.cpp
new file mode 100755 (executable)
index 0000000..d77e1c5
--- /dev/null
@@ -0,0 +1,747 @@
+// MSIS-00 Data
+// Adapted for use in JSBSim
+// David Culp, davidculp2@comcast.net
+
+/* -------------------------------------------------------------------- */
+/* ---------  N R L M S I S E - 0 0    M O D E L    2 0 0 1  ---------- */
+/* -------------------------------------------------------------------- */
+
+/* This file is part of the NRLMSISE-00  C source code package - release
+ * 20020503
+ *
+ * The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and
+ * Doug Drob. They also wrote a NRLMSISE-00 distribution package in 
+ * FORTRAN which is available at
+ * http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm
+ *
+ * Dominik Brodowski implemented and maintains this C version. You can
+ * reach him at devel@brodo.de. See the file "DOCUMENTATION" for details,
+ * and check http://www.brodo.de/english/pub/nrlmsise/index.html for
+ * updated releases of this package.
+ */
+
+
+
+/* ------------------------------------------------------------------- */
+/* ------------------------ BLOCK DATA GTD7BK ------------------------ */
+/* ------------------------------------------------------------------- */
+
+namespace JSBSim {
+
+/* TEMPERATURE */
+double pt[150] = {
+     9.86573E-01, 1.62228E-02, 1.55270E-02,-1.04323E-01,-3.75801E-03,
+    -1.18538E-03,-1.24043E-01, 4.56820E-03, 8.76018E-03,-1.36235E-01,
+    -3.52427E-02, 8.84181E-03,-5.92127E-03,-8.61650E+00, 0.00000E+00,
+     1.28492E-02, 0.00000E+00, 1.30096E+02, 1.04567E-02, 1.65686E-03,
+    -5.53887E-06, 2.97810E-03, 0.00000E+00, 5.13122E-03, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.27026E-06,
+     0.00000E+00, 6.74494E+00, 4.93933E-03, 2.21656E-03, 2.50802E-03,
+     0.00000E+00, 0.00000E+00,-2.08841E-02,-1.79873E+00, 1.45103E-03,
+     2.81769E-04,-1.44703E-03,-5.16394E-05, 8.47001E-02, 1.70147E-01,
+     5.72562E-03, 5.07493E-05, 4.36148E-03, 1.17863E-04, 4.74364E-03,
+     6.61278E-03, 4.34292E-05, 1.44373E-03, 2.41470E-05, 2.84426E-03,
+     8.56560E-04, 2.04028E-03, 0.00000E+00,-3.15994E+03,-2.46423E-03,
+     1.13843E-03, 4.20512E-04, 0.00000E+00,-9.77214E+01, 6.77794E-03,
+     5.27499E-03, 1.14936E-03, 0.00000E+00,-6.61311E-03,-1.84255E-02,
+    -1.96259E-02, 2.98618E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     6.44574E+02, 8.84668E-04, 5.05066E-04, 0.00000E+00, 4.02881E+03,
+    -1.89503E-03, 0.00000E+00, 0.00000E+00, 8.21407E-04, 2.06780E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -1.20410E-02,-3.63963E-03, 9.92070E-05,-1.15284E-04,-6.33059E-05,
+    -6.05545E-01, 8.34218E-03,-9.13036E+01, 3.71042E-04, 0.00000E+00,
+     4.19000E-04, 2.70928E-03, 3.31507E-03,-4.44508E-03,-4.96334E-03,
+    -1.60449E-03, 3.95119E-03, 2.48924E-03, 5.09815E-04, 4.05302E-03,
+     2.24076E-03, 0.00000E+00, 6.84256E-03, 4.66354E-04, 0.00000E+00,
+    -3.68328E-04, 0.00000E+00, 0.00000E+00,-1.46870E+02, 0.00000E+00,
+     0.00000E+00, 1.09501E-03, 4.65156E-04, 5.62583E-04, 3.21596E+00,
+     6.43168E-04, 3.14860E-03, 3.40738E-03, 1.78481E-03, 9.62532E-04,
+     5.58171E-04, 3.43731E+00,-2.33195E-01, 5.10289E-04, 0.00000E+00,
+     0.00000E+00,-9.25347E+04, 0.00000E+00,-1.99639E-03, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+};
+
+double pd[9][150] = {
+/*  HE DENSITY */ {
+     1.09979E+00,-4.88060E-02,-1.97501E-01,-9.10280E-02,-6.96558E-03,
+     2.42136E-02, 3.91333E-01,-7.20068E-03,-3.22718E-02, 1.41508E+00,
+     1.68194E-01, 1.85282E-02, 1.09384E-01,-7.24282E+00, 0.00000E+00,
+     2.96377E-01,-4.97210E-02, 1.04114E+02,-8.61108E-02,-7.29177E-04,
+     1.48998E-06, 1.08629E-03, 0.00000E+00, 0.00000E+00, 8.31090E-02,
+     1.12818E-01,-5.75005E-02,-1.29919E-02,-1.78849E-02,-2.86343E-06,
+     0.00000E+00,-1.51187E+02,-6.65902E-03, 0.00000E+00,-2.02069E-03,
+     0.00000E+00, 0.00000E+00, 4.32264E-02,-2.80444E+01,-3.26789E-03,
+     2.47461E-03, 0.00000E+00, 0.00000E+00, 9.82100E-02, 1.22714E-01,
+    -3.96450E-02, 0.00000E+00,-2.76489E-03, 0.00000E+00, 1.87723E-03,
+    -8.09813E-03, 4.34428E-05,-7.70932E-03, 0.00000E+00,-2.28894E-03,
+    -5.69070E-03,-5.22193E-03, 6.00692E-03,-7.80434E+03,-3.48336E-03,
+    -6.38362E-03,-1.82190E-03, 0.00000E+00,-7.58976E+01,-2.17875E-02,
+    -1.72524E-02,-9.06287E-03, 0.00000E+00, 2.44725E-02, 8.66040E-02,
+     1.05712E-01, 3.02543E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -6.01364E+03,-5.64668E-03,-2.54157E-03, 0.00000E+00, 3.15611E+02,
+    -5.69158E-03, 0.00000E+00, 0.00000E+00,-4.47216E-03,-4.49523E-03,
+     4.64428E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     4.51236E-02, 2.46520E-02, 6.17794E-03, 0.00000E+00, 0.00000E+00,
+    -3.62944E-01,-4.80022E-02,-7.57230E+01,-1.99656E-03, 0.00000E+00,
+    -5.18780E-03,-1.73990E-02,-9.03485E-03, 7.48465E-03, 1.53267E-02,
+     1.06296E-02, 1.18655E-02, 2.55569E-03, 1.69020E-03, 3.51936E-02,
+    -1.81242E-02, 0.00000E+00,-1.00529E-01,-5.10574E-03, 0.00000E+00,
+     2.10228E-03, 0.00000E+00, 0.00000E+00,-1.73255E+02, 5.07833E-01,
+    -2.41408E-01, 8.75414E-03, 2.77527E-03,-8.90353E-05,-5.25148E+00,
+    -5.83899E-03,-2.09122E-02,-9.63530E-03, 9.77164E-03, 4.07051E-03,
+     2.53555E-04,-5.52875E+00,-3.55993E-01,-2.49231E-03, 0.00000E+00,
+     0.00000E+00, 2.86026E+01, 0.00000E+00, 3.42722E-04, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}, /* O DENSITY */ {
+     1.02315E+00,-1.59710E-01,-1.06630E-01,-1.77074E-02,-4.42726E-03,
+     3.44803E-02, 4.45613E-02,-3.33751E-02,-5.73598E-02, 3.50360E-01,
+     6.33053E-02, 2.16221E-02, 5.42577E-02,-5.74193E+00, 0.00000E+00,
+     1.90891E-01,-1.39194E-02, 1.01102E+02, 8.16363E-02, 1.33717E-04,
+     6.54403E-06, 3.10295E-03, 0.00000E+00, 0.00000E+00, 5.38205E-02,
+     1.23910E-01,-1.39831E-02, 0.00000E+00, 0.00000E+00,-3.95915E-06,
+     0.00000E+00,-7.14651E-01,-5.01027E-03, 0.00000E+00,-3.24756E-03,
+     0.00000E+00, 0.00000E+00, 4.42173E-02,-1.31598E+01,-3.15626E-03,
+     1.24574E-03,-1.47626E-03,-1.55461E-03, 6.40682E-02, 1.34898E-01,
+    -2.42415E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.13666E-04,
+    -5.40373E-03, 2.61635E-05,-3.33012E-03, 0.00000E+00,-3.08101E-03,
+    -2.42679E-03,-3.36086E-03, 0.00000E+00,-1.18979E+03,-5.04738E-02,
+    -2.61547E-03,-1.03132E-03, 1.91583E-04,-8.38132E+01,-1.40517E-02,
+    -1.14167E-02,-4.08012E-03, 1.73522E-04,-1.39644E-02,-6.64128E-02,
+    -6.85152E-02,-1.34414E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     6.07916E+02,-4.12220E-03,-2.20996E-03, 0.00000E+00, 1.70277E+03,
+    -4.63015E-03, 0.00000E+00, 0.00000E+00,-2.25360E-03,-2.96204E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     3.92786E-02, 1.31186E-02,-1.78086E-03, 0.00000E+00, 0.00000E+00,
+    -3.90083E-01,-2.84741E-02,-7.78400E+01,-1.02601E-03, 0.00000E+00,
+    -7.26485E-04,-5.42181E-03,-5.59305E-03, 1.22825E-02, 1.23868E-02,
+     6.68835E-03,-1.03303E-02,-9.51903E-03, 2.70021E-04,-2.57084E-02,
+    -1.32430E-02, 0.00000E+00,-3.81000E-02,-3.16810E-03, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-9.05762E-04,-2.14590E-03,-1.17824E-03, 3.66732E+00,
+    -3.79729E-04,-6.13966E-03,-5.09082E-03,-1.96332E-03,-3.08280E-03,
+    -9.75222E-04, 4.03315E+00,-2.52710E-01, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}, /* N2 DENSITY */ {
+     1.16112E+00, 0.00000E+00, 0.00000E+00, 3.33725E-02, 0.00000E+00,
+     3.48637E-02,-5.44368E-03, 0.00000E+00,-6.73940E-02, 1.74754E-01,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00,
+     1.26733E-01, 0.00000E+00, 1.03154E+02, 5.52075E-02, 0.00000E+00,
+     0.00000E+00, 8.13525E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-2.50482E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.48894E-03,
+     6.16053E-04,-5.79716E-04, 2.95482E-03, 8.47001E-02, 1.70147E-01,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}, /* TLB */ {
+     9.44846E-01, 0.00000E+00, 0.00000E+00,-3.08617E-02, 0.00000E+00,
+    -2.44019E-02, 6.48607E-03, 0.00000E+00, 3.08181E-02, 4.59392E-02,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00,
+     2.13260E-02, 0.00000E+00,-3.56958E+02, 0.00000E+00, 1.82278E-04,
+     0.00000E+00, 3.07472E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 3.83054E-03, 0.00000E+00, 0.00000E+00,
+    -1.93065E-03,-1.45090E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-1.23493E-03, 1.36736E-03, 8.47001E-02, 1.70147E-01,
+     3.71469E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     5.10250E-03, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 3.68756E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}, /* O2 DENSITY */ {
+     1.35580E+00, 1.44816E-01, 0.00000E+00, 6.07767E-02, 0.00000E+00,
+     2.94777E-02, 7.46900E-02, 0.00000E+00,-9.23822E-02, 8.57342E-02,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 2.38636E+01, 0.00000E+00,
+     7.71653E-02, 0.00000E+00, 8.18751E+01, 1.87736E-02, 0.00000E+00,
+     0.00000E+00, 1.49667E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-3.67874E+02, 5.48158E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
+     1.22631E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     8.17187E-03, 3.71617E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.10826E-03,
+    -3.13640E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -7.35742E-02,-5.00266E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 1.94965E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}, /* AR DENSITY */ {
+     1.04761E+00, 2.00165E-01, 2.37697E-01, 3.68552E-02, 0.00000E+00,
+     3.57202E-02,-2.14075E-01, 0.00000E+00,-1.08018E-01,-3.73981E-01,
+     0.00000E+00, 3.10022E-02,-1.16305E-03,-2.07596E+01, 0.00000E+00,
+     8.64502E-02, 0.00000E+00, 9.74908E+01, 5.16707E-02, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 3.46193E+02, 1.34297E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.48509E-03,
+    -1.54689E-04, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
+     1.47753E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     1.89320E-02, 3.68181E-05, 1.32570E-02, 0.00000E+00, 0.00000E+00,
+     3.59719E-03, 7.44328E-03,-1.00023E-03,-6.50528E+03, 0.00000E+00,
+     1.03485E-02,-1.00983E-03,-4.06916E-03,-6.60864E+01,-1.71533E-02,
+     1.10605E-02, 1.20300E-02,-5.20034E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -2.62769E+03, 7.13755E-03, 4.17999E-03, 0.00000E+00, 1.25910E+04,
+     0.00000E+00, 0.00000E+00, 0.00000E+00,-2.23595E-03, 4.60217E-03,
+     5.71794E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -3.18353E-02,-2.35526E-02,-1.36189E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.03522E-02,-6.67837E+01,-1.09724E-03, 0.00000E+00,
+    -1.38821E-02, 1.60468E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.51574E-02,
+    -5.44470E-04, 0.00000E+00, 7.28224E-02, 6.59413E-02, 0.00000E+00,
+    -5.15692E-03, 0.00000E+00, 0.00000E+00,-3.70367E+03, 0.00000E+00,
+     0.00000E+00, 1.36131E-02, 5.38153E-03, 0.00000E+00, 4.76285E+00,
+    -1.75677E-02, 2.26301E-02, 0.00000E+00, 1.76631E-02, 4.77162E-03,
+     0.00000E+00, 5.39354E+00, 0.00000E+00,-7.51710E-03, 0.00000E+00,
+     0.00000E+00,-8.82736E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}, /* H DENSITY */ {
+     1.26376E+00,-2.14304E-01,-1.49984E-01, 2.30404E-01, 2.98237E-02,
+     2.68673E-02, 2.96228E-01, 2.21900E-02,-2.07655E-02, 4.52506E-01,
+     1.20105E-01, 3.24420E-02, 4.24816E-02,-9.14313E+00, 0.00000E+00,
+     2.47178E-02,-2.88229E-02, 8.12805E+01, 5.10380E-02,-5.80611E-03,
+     2.51236E-05,-1.24083E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02,
+     1.58727E-01,-3.48190E-02, 0.00000E+00, 0.00000E+00, 2.89885E-05,
+     0.00000E+00, 1.53595E+02,-1.68604E-02, 0.00000E+00, 1.01015E-02,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.84552E-04,
+    -1.22181E-03, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
+    -1.04927E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.91313E-03,
+    -2.30501E-02, 3.14758E-05, 0.00000E+00, 0.00000E+00, 1.26956E-02,
+     8.35489E-03, 3.10513E-04, 0.00000E+00, 3.42119E+03,-2.45017E-03,
+    -4.27154E-04, 5.45152E-04, 1.89896E-03, 2.89121E+01,-6.49973E-03,
+    -1.93855E-02,-1.48492E-02, 0.00000E+00,-5.10576E-02, 7.87306E-02,
+     9.51981E-02,-1.49422E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     2.65503E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 6.37110E-03, 3.24789E-04,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     6.14274E-02, 1.00376E-02,-8.41083E-04, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-1.27099E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -3.94077E-03,-1.28601E-02,-7.97616E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-6.71465E-03,-1.69799E-03, 1.93772E-03, 3.81140E+00,
+    -7.79290E-03,-1.82589E-02,-1.25860E-02,-1.04311E-02,-3.02465E-03,
+     2.43063E-03, 3.63237E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}, /* N DENSITY */ {
+     7.09557E+01,-3.26740E-01, 0.00000E+00,-5.16829E-01,-1.71664E-03,
+     9.09310E-02,-6.71500E-01,-1.47771E-01,-9.27471E-02,-2.30862E-01,
+    -1.56410E-01, 1.34455E-02,-1.19717E-01, 2.52151E+00, 0.00000E+00,
+    -2.41582E-01, 5.92939E-02, 4.39756E+00, 9.15280E-02, 4.41292E-03,
+     0.00000E+00, 8.66807E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02,
+     1.58727E-01, 9.74701E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 6.70217E+01,-1.31660E-03, 0.00000E+00,-1.65317E-02,
+     0.00000E+00, 0.00000E+00, 8.50247E-02, 2.77428E+01, 4.98658E-03,
+     6.15115E-03, 9.50156E-03,-2.12723E-02, 8.47001E-02, 1.70147E-01,
+    -2.38645E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.37380E-03,
+    -8.41918E-03, 2.80145E-05, 7.12383E-03, 0.00000E+00,-1.66209E-02,
+     1.03533E-04,-1.68898E-02, 0.00000E+00, 3.64526E+03, 0.00000E+00,
+     6.54077E-03, 3.69130E-04, 9.94419E-04, 8.42803E+01,-1.16124E-02,
+    -7.74414E-03,-1.68844E-03, 1.42809E-03,-1.92955E-03, 1.17225E-01,
+    -2.41512E-02, 1.50521E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     1.60261E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00,-3.54403E-04,-1.87270E-02,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     2.76439E-02, 6.43207E-03,-3.54300E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-2.80221E-02, 8.11228E+01,-6.75255E-04, 0.00000E+00,
+    -1.05162E-02,-3.48292E-03,-6.97321E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-1.45546E-03,-1.31970E-02,-3.57751E-03,-1.09021E+00,
+    -1.50181E-02,-7.12841E-03,-6.64590E-03,-3.52610E-03,-1.87773E-02,
+    -2.22432E-03,-3.93895E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 
+}, /* HOT O DENSITY */ {
+     6.04050E-02, 1.57034E+00, 2.99387E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.51018E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00,-8.61650E+00, 1.26454E-02,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 5.50878E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 6.23881E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01,
+    -9.45934E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+}};
+/* S PARAM  */
+double ps[150] = {
+     9.56827E-01, 6.20637E-02, 3.18433E-02, 0.00000E+00, 0.00000E+00,
+     3.94900E-02, 0.00000E+00, 0.00000E+00,-9.24882E-03,-7.94023E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.74677E-03, 0.00000E+00, 1.54951E-02, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00,-6.99007E-04, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 1.24362E-02,-5.28756E-03, 8.47001E-02, 1.70147E-01,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+};
+
+/* TURBO */
+double pdl[2][25] = {
+   { 1.09930E+00, 3.90631E+00, 3.07165E+00, 9.86161E-01, 1.63536E+01,
+     4.63830E+00, 1.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 1.28840E+00, 3.10302E-02, 1.18339E-01 }, 
+   { 1.00000E+00, 7.00000E-01, 1.15020E+00, 3.44689E+00, 1.28840E+00,
+     1.00000E+00, 1.08738E+00, 1.22947E+00, 1.10016E+00, 7.34129E-01,
+     1.15241E+00, 2.22784E+00, 7.95046E-01, 4.01612E+00, 4.47749E+00,
+     1.23435E+02,-7.60535E-02, 1.68986E-06, 7.44294E-01, 1.03604E+00,
+     1.72783E+02, 1.15020E+00, 3.44689E+00,-7.46230E-01, 9.49154E-01 }
+};
+/* LOWER BOUNDARY */
+double ptm[50] = {
+     1.04130E+03, 3.86000E+02, 1.95000E+02, 1.66728E+01, 2.13000E+02,
+     1.20000E+02, 2.40000E+02, 1.87000E+02,-2.00000E+00, 0.00000E+00
+};
+double pdm[8][10] = {
+{    2.45600E+07, 6.71072E-06, 1.00000E+02, 0.00000E+00, 1.10000E+02,
+     1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },\
+{    8.59400E+10, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02,
+     1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 },\
+{    2.81000E+11, 0.00000E+00, 1.05000E+02, 2.80000E+01, 2.89500E+01,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },
+{    3.30000E+10, 2.68270E-01, 1.05000E+02, 1.00000E+00, 1.10000E+02,
+     1.00000E+01, 1.10000E+02,-1.00000E+01, 0.00000E+00, 0.00000E+00 },
+{    1.33000E+09, 1.19615E-02, 1.05000E+02, 0.00000E+00, 1.10000E+02,
+     1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00 },
+{    1.76100E+05, 1.00000E+00, 9.50000E+01,-8.00000E+00, 1.10000E+02,
+     1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00, },
+{    1.00000E+07, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02,
+     1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00 },
+{    1.00000E+06, 1.00000E+00, 1.05000E+02,-8.00000E+00, 5.50000E+02,
+     7.60000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 4.00000E+03 }};
+
+
+double ptl[4][100] = {
+/* TN1(2) */ {
+     1.00858E+00, 4.56011E-02,-2.22972E-02,-5.44388E-02, 5.23136E-04,
+    -1.88849E-02, 5.23707E-02,-9.43646E-03, 6.31707E-03,-7.80460E-02,
+    -4.88430E-02, 0.00000E+00, 0.00000E+00,-7.60250E+00, 0.00000E+00,
+    -1.44635E-02,-1.76843E-02,-1.21517E+02, 2.85647E-02, 0.00000E+00,
+     0.00000E+00, 6.31792E-04, 0.00000E+00, 5.77197E-03, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-8.90272E+03, 3.30611E-03, 3.02172E-03, 0.00000E+00,
+    -2.13673E-03,-3.20910E-04, 0.00000E+00, 0.00000E+00, 2.76034E-03,
+     2.82487E-03,-2.97592E-04,-4.21534E-03, 8.47001E-02, 1.70147E-01,
+     8.96456E-03, 0.00000E+00,-1.08596E-02, 0.00000E+00, 0.00000E+00,
+     5.57917E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 9.65405E-03, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /*  TN1(3) */ {
+     9.39664E-01, 8.56514E-02,-6.79989E-03, 2.65929E-02,-4.74283E-03,
+     1.21855E-02,-2.14905E-02, 6.49651E-03,-2.05477E-02,-4.24952E-02,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 1.19148E+01, 0.00000E+00,
+     1.18777E-02,-7.28230E-02,-8.15965E+01, 1.73887E-02, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-1.44691E-02, 2.80259E-04, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.16584E+02, 3.18713E-03, 7.37479E-03, 0.00000E+00,
+    -2.55018E-03,-3.92806E-03, 0.00000E+00, 0.00000E+00,-2.89757E-03,
+    -1.33549E-03, 1.02661E-03, 3.53775E-04, 8.47001E-02, 1.70147E-01,
+    -9.17497E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     3.56082E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-1.00902E-02, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN1(4) */ {
+     9.85982E-01,-4.55435E-02, 1.21106E-02, 2.04127E-02,-2.40836E-03,
+     1.11383E-02,-4.51926E-02, 1.35074E-02,-6.54139E-03, 1.15275E-01,
+     1.28247E-01, 0.00000E+00, 0.00000E+00,-5.30705E+00, 0.00000E+00,
+    -3.79332E-02,-6.24741E-02, 7.71062E-01, 2.96315E-02, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 6.81051E-03,-4.34767E-03, 8.66784E-02,
+     1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 1.07003E+01,-2.76907E-03, 4.32474E-04, 0.00000E+00,
+     1.31497E-03,-6.47517E-04, 0.00000E+00,-2.20621E+01,-1.10804E-03,
+    -8.09338E-04, 4.18184E-04, 4.29650E-03, 8.47001E-02, 1.70147E-01,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -4.04337E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-9.52550E-04,
+     8.56253E-04, 4.33114E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.21223E-03,
+     2.38694E-04, 9.15245E-04, 1.28385E-03, 8.67668E-04,-5.61425E-06,
+     1.04445E+00, 3.41112E+01, 0.00000E+00,-8.40704E-01,-2.39639E+02,
+     7.06668E-01,-2.05873E+01,-3.63696E-01, 2.39245E+01, 0.00000E+00,
+    -1.06657E-03,-7.67292E-04, 1.54534E-04, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN1(5) TN2(1) */ {
+     1.00320E+00, 3.83501E-02,-2.38983E-03, 2.83950E-03, 4.20956E-03,
+     5.86619E-04, 2.19054E-02,-1.00946E-02,-3.50259E-03, 4.17392E-02,
+    -8.44404E-03, 0.00000E+00, 0.00000E+00, 4.96949E+00, 0.00000E+00,
+    -7.06478E-03,-1.46494E-02, 3.13258E+01,-1.86493E-03, 0.00000E+00,
+    -1.67499E-02, 0.00000E+00, 0.00000E+00, 5.12686E-04, 8.66784E-02,
+     1.58727E-01,-4.64167E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     4.37353E-03,-1.99069E+02, 0.00000E+00,-5.34884E-03, 0.00000E+00,
+     1.62458E-03, 2.93016E-03, 2.67926E-03, 5.90449E+02, 0.00000E+00,
+     0.00000E+00,-1.17266E-03,-3.58890E-04, 8.47001E-02, 1.70147E-01,
+     0.00000E+00, 0.00000E+00, 1.38673E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.60571E-03,
+     6.28078E-04, 5.05469E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.57829E-03,
+    -4.00855E-04, 5.04077E-05,-1.39001E-03,-2.33406E-03,-4.81197E-04,
+     1.46758E+00, 6.20332E+00, 0.00000E+00, 3.66476E-01,-6.19760E+01,
+     3.09198E-01,-1.98999E+01, 0.00000E+00,-3.29933E+02, 0.00000E+00,
+    -1.10080E-03,-9.39310E-05, 1.39638E-04, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+} };
+
+double pma[10][100] = {
+/* TN2(2) */ {
+     9.81637E-01,-1.41317E-03, 3.87323E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.58707E-02,
+    -8.63658E-03, 0.00000E+00, 0.00000E+00,-2.02226E+00, 0.00000E+00,
+    -8.69424E-03,-1.91397E-02, 8.76779E+01, 4.52188E-03, 0.00000E+00,
+     2.23760E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-7.07572E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+    -4.11210E-03, 3.50060E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-8.36657E-03, 1.61347E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-1.45130E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.24152E-03,
+     6.43365E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.33255E-03,
+     2.42657E-03, 1.60666E-03,-1.85728E-03,-1.46874E-03,-4.79163E-06,
+     1.22464E+00, 3.53510E+01, 0.00000E+00, 4.49223E-01,-4.77466E+01,
+     4.70681E-01, 8.41861E+00,-2.88198E-01, 1.67854E+02, 0.00000E+00,
+     7.11493E-04, 6.05601E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN2(3) */ {
+     1.00422E+00,-7.11212E-03, 5.24480E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.28914E-02,
+    -2.41301E-02, 0.00000E+00, 0.00000E+00,-2.12219E+01,-1.03830E-02,
+    -3.28077E-03, 1.65727E-02, 1.68564E+00,-6.68154E-03, 0.00000E+00,
+     1.45155E-02, 0.00000E+00, 8.42365E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-4.34645E-03, 0.00000E+00, 0.00000E+00, 2.16780E-02,
+     0.00000E+00,-1.38459E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 7.04573E-03,-4.73204E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 1.08767E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.08279E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.21769E-04,
+    -2.27387E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.26769E-03,
+     3.16901E-03, 4.60316E-04,-1.01431E-04, 1.02131E-03, 9.96601E-04,
+     1.25707E+00, 2.50114E+01, 0.00000E+00, 4.24472E-01,-2.77655E+01,
+     3.44625E-01, 2.75412E+01, 0.00000E+00, 7.94251E+02, 0.00000E+00,
+     2.45835E-03, 1.38871E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN2(4) TN3(1) */ {
+     1.01890E+00,-2.46603E-02, 1.00078E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.70977E-02,
+    -4.02286E-02, 0.00000E+00, 0.00000E+00,-2.29466E+01,-7.47019E-03,
+     2.26580E-03, 2.63931E-02, 3.72625E+01,-6.39041E-03, 0.00000E+00,
+     9.58383E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-1.85291E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 1.39717E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 9.19771E-03,-3.69121E+02, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-1.57067E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.07265E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.92953E-03,
+    -2.77739E-03,-4.40092E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.47280E-03,
+     2.95035E-04,-1.81246E-03, 2.81945E-03, 4.27296E-03, 9.78863E-04,
+     1.40545E+00,-6.19173E+00, 0.00000E+00, 0.00000E+00,-7.93632E+01,
+     4.44643E-01,-4.03085E+02, 0.00000E+00, 1.15603E+01, 0.00000E+00,
+     2.25068E-03, 8.48557E-04,-2.98493E-04, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN3(2) */ {
+     9.75801E-01, 3.80680E-02,-3.05198E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.85575E-02,
+     5.04057E-02, 0.00000E+00, 0.00000E+00,-1.76046E+02, 1.44594E-02,
+    -1.48297E-03,-3.68560E-03, 3.02185E+01,-3.23338E-03, 0.00000E+00,
+     1.53569E-02, 0.00000E+00,-1.15558E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 4.89620E-03, 0.00000E+00, 0.00000E+00,-1.00616E-02,
+    -8.21324E-03,-1.57757E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 6.63564E-03, 4.58410E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-2.51280E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 9.91215E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.73148E-04,
+    -1.29648E-03,-7.32026E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.68110E-03,
+    -4.66003E-03,-1.31567E-03,-7.39390E-04, 6.32499E-04,-4.65588E-04,
+    -1.29785E+00,-1.57139E+02, 0.00000E+00, 2.58350E-01,-3.69453E+01,
+     4.10672E-01, 9.78196E+00,-1.52064E-01,-3.85084E+03, 0.00000E+00,
+    -8.52706E-04,-1.40945E-03,-7.26786E-04, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN3(3) */ {
+     9.60722E-01, 7.03757E-02,-3.00266E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.22671E-02,
+     4.10423E-02, 0.00000E+00, 0.00000E+00,-1.63070E+02, 1.06073E-02,
+     5.40747E-04, 7.79481E-03, 1.44908E+02, 1.51484E-04, 0.00000E+00,
+     1.97547E-02, 0.00000E+00,-1.41844E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 5.77884E-03, 0.00000E+00, 0.00000E+00, 9.74319E-03,
+     0.00000E+00,-2.88015E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-4.44902E-03,-2.92760E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 2.34419E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.36685E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.65325E-04,
+    -5.50628E-04, 3.31465E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.06179E-03,
+    -3.08575E-03,-7.93589E-04,-1.08629E-04, 5.95511E-04,-9.05050E-04,
+     1.18997E+00, 4.15924E+01, 0.00000E+00,-4.72064E-01,-9.47150E+02,
+     3.98723E-01, 1.98304E+01, 0.00000E+00, 3.73219E+03, 0.00000E+00,
+    -1.50040E-03,-1.14933E-03,-1.56769E-04, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN3(4) */ {
+     1.03123E+00,-7.05124E-02, 8.71615E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.82621E-02,
+    -9.80975E-03, 0.00000E+00, 0.00000E+00, 2.89286E+01, 9.57341E-03,
+     0.00000E+00, 0.00000E+00, 8.66153E+01, 7.91938E-04, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 4.68917E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 7.86638E-03, 0.00000E+00, 0.00000E+00, 9.90827E-03,
+     0.00000E+00, 6.55573E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00,-4.00200E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 7.07457E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.72268E-03,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.04970E-04,
+     1.21560E-03,-8.05579E-06, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.49941E-03,
+    -4.57256E-04,-1.59311E-04, 2.96481E-04,-1.77318E-03,-6.37918E-04,
+     1.02395E+00, 1.28172E+01, 0.00000E+00, 1.49903E-01,-2.63818E+01,
+     0.00000E+00, 4.70628E+01,-2.22139E-01, 4.82292E-02, 0.00000E+00,
+    -8.67075E-04,-5.86479E-04, 5.32462E-04, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TN3(5) SURFACE TEMP TSL */ {
+     1.00828E+00,-9.10404E-02,-2.26549E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.32420E-02,
+    -9.08925E-03, 0.00000E+00, 0.00000E+00, 3.36105E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-1.24957E+01,-5.87939E-03, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.79765E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 2.01237E+03, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-1.75553E-02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.29699E-03,
+     1.26659E-03, 2.68402E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.17894E-03,
+     1.48746E-03, 1.06478E-04, 1.34743E-04,-2.20939E-03,-6.23523E-04,
+     6.36539E-01, 1.13621E+01, 0.00000E+00,-3.93777E-01, 2.38687E+03,
+     0.00000E+00, 6.61865E+02,-1.21434E-01, 9.27608E+00, 0.00000E+00,
+     1.68478E-04, 1.24892E-03, 1.71345E-03, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TGN3(2) SURFACE GRAD TSLG */ {
+     1.57293E+00,-6.78400E-01, 6.47500E-01, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.62974E-02,
+    -3.60423E-01, 0.00000E+00, 0.00000E+00, 1.28358E+02, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 4.68038E+01, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-1.67898E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.90994E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 3.15706E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TGN2(1) TGN1(2) */ {
+     8.60028E-01, 3.77052E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.17570E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 7.77757E-03, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 1.01024E+02, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 6.54251E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.56959E-02,
+     1.91001E-02, 3.15971E-02, 1.00982E-02,-6.71565E-03, 2.57693E-03,
+     1.38692E+00, 2.82132E-01, 0.00000E+00, 0.00000E+00, 3.81511E+02,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+}, /* TGN3(1) TGN2(2) */ {
+     1.06029E+00,-5.25231E-02, 3.73034E-01, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.31072E-02,
+    -3.88409E-01, 0.00000E+00, 0.00000E+00,-1.65295E+02,-2.13801E-01,
+    -4.38916E-02,-3.22716E-01,-8.82393E+01, 1.18458E-01, 0.00000E+00,
+    -4.35863E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00,-1.19782E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 2.62229E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00,-5.37443E+01, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00,-4.55788E-01, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.84009E-02,
+     3.96733E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.05494E-02,
+     7.39617E-02, 1.92200E-02,-8.46151E-03,-1.34244E-02, 1.96338E-02,
+     1.50421E+00, 1.88368E+01, 0.00000E+00, 0.00000E+00,-5.13114E+01,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     5.11923E-02, 3.61225E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00
+} };
+/* SEMIANNUAL MULT SAM */
+double sam[100] = {
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,
+     0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00
+};
+/* MIDDLE ATMOSPHERE AVERAGES */
+double pavgm[10] = {
+     2.61000E+02, 2.64000E+02, 2.29000E+02, 2.17000E+02, 2.17000E+02,
+     2.23000E+02, 2.86760E+02,-2.93940E+00, 2.50000E+00, 0.00000E+00 };
+} // namespace
diff --git a/src/FDM/JSBSim/models/atmosphere/FGMars.cpp b/src/FDM/JSBSim/models/atmosphere/FGMars.cpp
new file mode 100755 (executable)
index 0000000..2f9eec4
--- /dev/null
@@ -0,0 +1,331 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGMars.cpp
+ Author:       Jon Berndt
+ Date started: 1/4/04
+ Purpose:      Models the Martian atmosphere very simply
+ Called by:    FGFDMExec
+
+ ------------- Copyright (C) 2004  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
+--------------------------------------------------------------------------------
+Models the Martian atmosphere.
+
+HISTORY
+--------------------------------------------------------------------------------
+1/04/2004   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGMars.h"
+#include "FGState.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_MARS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGMars::FGMars(FGFDMExec* fdmex) : FGAtmosphere(fdmex)
+{
+  Name = "FGMars";
+  Reng = 53.5 * 44.01;
+
+/*
+  lastIndex = 0;
+  h = 0.0;
+  psiw = 0.0;
+
+  MagnitudedAccelDt = MagnitudeAccel = Magnitude = 0.0;
+//   turbType = ttNone;
+  turbType = ttStandard;
+//   turbType = ttBerndt;
+  TurbGain = 0.0;
+  TurbRate = 1.0;
+*/
+
+  bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/*
+FGMars::~FGMars()
+{
+  unbind();
+  Debug(1);
+}
+*/
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGMars::InitModel(void)
+{
+  FGModel::InitModel();
+
+  Calculate(h);
+  SLtemperature = intTemperature;
+  SLpressure    = intPressure;
+  SLdensity     = intDensity;
+  SLsoundspeed  = sqrt(SHRatio*Reng*intTemperature);
+  rSLtemperature = 1.0/intTemperature;
+  rSLpressure    = 1.0/intPressure;
+  rSLdensity     = 1.0/intDensity;
+  rSLsoundspeed  = 1.0/SLsoundspeed;
+  temperature = &intTemperature;
+  pressure = &intPressure;
+  density = &intDensity;
+
+  useExternal=false;
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGMars::Run(void)
+{
+  if (FGModel::Run()) return true;
+  if (FDMExec->Holding()) return false;
+
+  //do temp, pressure, and density first
+  if (!useExternal) {
+    h = Propagate->Geth();
+    Calculate(h);
+  }
+
+  if (turbType != ttNone) {
+    Turbulence();
+    vWindNED += vTurbulence;
+  }
+
+  if (vWindNED(1) != 0.0) psiw = atan2( vWindNED(2), vWindNED(1) );
+
+  if (psiw < 0) psiw += 2*M_PI;
+
+  soundspeed = sqrt(SHRatio*Reng*(*temperature));
+
+  Debug(2);
+
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMars::Calculate(double altitude)
+{
+  //Calculate reftemp, refpress, and density
+
+  // LIMIT the temperatures so they do not descend below absolute zero.
+
+  if (altitude < 22960.0) {
+    intTemperature = -25.68 - 0.000548*altitude; // Deg Fahrenheit
+  } else {
+    intTemperature = -10.34 - 0.001217*altitude; // Deg Fahrenheit
+  }
+  intPressure = 14.62*exp(-0.00003*altitude); // psf - 14.62 psf =~ 7 millibars
+  intDensity = intPressure/(Reng*intTemperature); // slugs/ft^3 (needs deg R. as input
+
+  //cout << "Atmosphere:  h=" << altitude << " rho= " << intDensity << endl;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// square a value, but preserve the original sign
+
+static inline double
+square_signed (double value)
+{
+  if (value < 0)
+    return value * value * -1;
+  else
+    return value * value;
+}
+
+void FGMars::Turbulence(void)
+{
+  switch (turbType) {
+  case ttStandard: {
+    vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
+    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;
+                                // Scale the magnitude so that it moves
+                                // away from the peaks
+    MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
+                         (1 + fabs(Magnitude)));
+    MagnitudeAccel    += MagnitudedAccelDt*rate*TurbRate*State->Getdt();
+    Magnitude         += MagnitudeAccel*rate*State->Getdt();
+
+    vDirectiondAccelDt.Normalize();
+
+                                // deemphasise non-vertical forces
+    vDirectiondAccelDt(eX) = square_signed(vDirectiondAccelDt(eX));
+    vDirectiondAccelDt(eY) = square_signed(vDirectiondAccelDt(eY));
+
+    vDirectionAccel += vDirectiondAccelDt*rate*TurbRate*State->Getdt();
+    vDirectionAccel.Normalize();
+    vDirection      += vDirectionAccel*rate*State->Getdt();
+
+    vDirection.Normalize();
+
+                                // Diminish turbulence within three wingspans
+                                // of the ground
+    vTurbulence = TurbGain * Magnitude * vDirection;
+    double HOverBMAC = Auxiliary->GetHOverBMAC();
+    if (HOverBMAC < 3.0)
+        vTurbulence *= (HOverBMAC / 3.0) * (HOverBMAC / 3.0);
+
+    vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
+
+    vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
+    vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
+//     if (Aircraft->GetHTailArm() != 0.0)
+//       vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
+//     else
+//       vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
+
+    if (Aircraft->GetVTailArm())
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
+    else
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
+
+                                // Clear the horizontal forces
+                                // actually felt by the plane, now
+                                // that we've used them to calculate
+                                // moments.
+    vTurbulence(eX) = 0.0;
+    vTurbulence(eY) = 0.0;
+
+    break;
+  }
+  case ttBerndt: {
+    vDirectiondAccelDt(eX) = 1 - 2.0*(double(rand())/double(RAND_MAX));
+    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();
+
+    vDirectiondAccelDt.Normalize();
+    vDirectionAccel += vDirectiondAccelDt*rate*State->Getdt();
+    vDirectionAccel.Normalize();
+    vDirection      += vDirectionAccel*rate*State->Getdt();
+
+                                // Diminish z-vector within two wingspans
+                                // of the ground
+    double HOverBMAC = Auxiliary->GetHOverBMAC();
+    if (HOverBMAC < 2.0)
+        vDirection(eZ) *= HOverBMAC / 2.0;
+
+    vDirection.Normalize();
+
+    vTurbulence = TurbGain*Magnitude * vDirection;
+    vTurbulenceGrad = TurbGain*MagnitudeAccel * vDirection;
+
+    vBodyTurbGrad = Propagate->GetTl2b()*vTurbulenceGrad;
+    vTurbPQR(eP) = vBodyTurbGrad(eY)/Aircraft->GetWingSpan();
+    if (Aircraft->GetHTailArm() != 0.0)
+      vTurbPQR(eQ) = vBodyTurbGrad(eZ)/Aircraft->GetHTailArm();
+    else
+      vTurbPQR(eQ) = vBodyTurbGrad(eZ)/10.0;
+
+    if (Aircraft->GetVTailArm())
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/Aircraft->GetVTailArm();
+    else
+      vTurbPQR(eR) = vBodyTurbGrad(eX)/10.0;
+
+    break;
+  }
+  default:
+    break;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGMars::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: FGMars" << endl;
+    if (from == 1) cout << "Destroyed:    FGMars" << 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 & 32) { // Turbulence
+    if (frame == 0 && from == 2) {
+      cout << "vTurbulence(X), vTurbulence(Y), vTurbulence(Z), "
+           << "vTurbulenceGrad(X), vTurbulenceGrad(Y), vTurbulenceGrad(Z), "
+           << "vDirection(X), vDirection(Y), vDirection(Z), "
+           << "Magnitude, "
+           << "vTurbPQR(P), vTurbPQR(Q), vTurbPQR(R), " << endl;
+    } else if (from == 2) {
+      cout << vTurbulence << ", " << vTurbulenceGrad << ", " << vDirection << ", " << Magnitude << ", " << vTurbPQR << endl;
+    }
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/models/atmosphere/FGMars.h b/src/FDM/JSBSim/models/atmosphere/FGMars.h
new file mode 100755 (executable)
index 0000000..68f24e6
--- /dev/null
@@ -0,0 +1,182 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGMars.h
+ Author:       Jon Berndt
+ Date started: 01/05/2004
+ ------------- Copyright (C) 2004  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/2004   JSB   Created
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGMars_H
+#define FGMars_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <models/FGAtmosphere.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_MARS "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models the Martian atmosphere.
+    @author Jon Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGMars : public FGAtmosphere {
+public:
+
+  /// Constructor
+  FGMars(FGFDMExec*);
+  /// Destructor
+  ~FGMars();
+  /** Runs the Martian atmosphere model; called by the Executive
+      @return false if no error */
+  bool Run(void);
+
+  bool InitModel(void);
+
+  /// Returns the temperature in degrees Rankine.
+  inline double GetTemperature(void) const {return *temperature;}
+  /** Returns the density in slugs/ft^3.
+      <i>This function may <b>only</b> be used if Run() is called first.</i> */
+  inline double GetDensity(void)  const {return *density;}
+  /// Returns the pressure in psf.
+  inline double GetPressure(void)  const {return *pressure;}
+  /// Returns the speed of sound in ft/sec.
+  inline double GetSoundSpeed(void) const {return soundspeed;}
+
+  /// Returns the sea level temperature in degrees Rankine.
+  inline double GetTemperatureSL(void) const { return SLtemperature; }
+  /// Returns the sea level density in slugs/ft^3
+  inline double GetDensitySL(void)  const { return SLdensity; }
+  /// Returns the sea level pressure in psf.
+  inline double GetPressureSL(void) const { return SLpressure; }
+  /// Returns the sea level speed of sound in ft/sec.
+  inline double GetSoundSpeedSL(void) const { return SLsoundspeed; }
+
+  /// Returns the ratio of at-altitude temperature over the sea level value.
+  inline double GetTemperatureRatio(void) const { return (*temperature)*rSLtemperature; }
+  /// Returns the ratio of at-altitude density over the sea level value.
+  inline double GetDensityRatio(void) const { return (*density)*rSLdensity; }
+  /// Returns the ratio of at-altitude pressure over the sea level value.
+  inline double GetPressureRatio(void) const { return (*pressure)*rSLpressure; }
+  /// Returns the ratio of at-altitude sound speed over the sea level value.
+  inline double GetSoundSpeedRatio(void) const { return soundspeed*rSLsoundspeed; }
+
+  /// Tells the simulator to use an externally calculated atmosphere model.
+  void UseExternal(void);
+  /// Tells the simulator to use the internal atmosphere model.
+  void UseInternal(void);  //this is the default
+  /// Gets the boolean that tells if the external atmosphere model is being used.
+  bool External(void) { return useExternal; }
+
+  /// Provides the external atmosphere model with an interface to set the temperature.
+  inline void SetExTemperature(double t)  { exTemperature=t; }
+  /// Provides the external atmosphere model with an interface to set the density.
+  inline void SetExDensity(double d)      { exDensity=d; }
+  /// Provides the external atmosphere model with an interface to set the pressure.
+  inline void SetExPressure(double p)     { exPressure=p; }
+
+  /// Sets the wind components in NED frame.
+  inline void SetWindNED(double wN, double wE, double wD) { vWindNED(1)=wN; vWindNED(2)=wE; vWindNED(3)=wD;}
+
+  /// Retrieves the wind components in NED frame.
+  inline FGColumnVector3& GetWindNED(void) { return vWindNED; }
+  
+  /** Retrieves the wind direction. The direction is defined as north=0 and
+      increases counterclockwise. The wind heading is returned in radians.*/
+  inline double GetWindPsi(void) const { return psiw; }
+  
+  inline void SetTurbGain(double tt) {TurbGain = tt;}
+  inline void SetTurbRate(double tt) {TurbRate = tt;}
+  
+  inline double GetTurbPQR(int idx) const {return vTurbPQR(idx);}
+  inline FGColumnVector3& GetTurbPQR(void) {return vTurbPQR;}
+  
+  void bind(void);
+  void unbind(void);
+
+  
+private:
+  double rho;
+
+  enum tType {ttStandard, ttBerndt, ttNone} turbType;
+
+  int lastIndex;
+  double h;
+  double htab[8];
+  double SLtemperature,SLdensity,SLpressure,SLsoundspeed;
+  double rSLtemperature,rSLdensity,rSLpressure,rSLsoundspeed; //reciprocals
+  double *temperature,*density,*pressure;
+  double soundspeed;
+  bool useExternal;
+  double exTemperature,exDensity,exPressure;
+  double intTemperature, intDensity, intPressure;
+  
+  double MagnitudedAccelDt, MagnitudeAccel, Magnitude;
+  double TurbGain;
+  double TurbRate;
+  FGColumnVector3 vDirectiondAccelDt;
+  FGColumnVector3 vDirectionAccel;
+  FGColumnVector3 vDirection;
+  FGColumnVector3 vTurbulence;
+  FGColumnVector3 vTurbulenceGrad;
+  FGColumnVector3 vBodyTurbGrad;
+  FGColumnVector3 vTurbPQR;
+
+  FGColumnVector3 vWindNED;
+  double psiw;
+
+  void Calculate(double altitude);
+  void Turbulence(void);
+  void Debug(int from);
+};
+
+} // namespace JSBSim
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/atmosphere/Makefile.am b/src/FDM/JSBSim/models/atmosphere/Makefile.am
new file mode 100644 (file)
index 0000000..c4fc9d8
--- /dev/null
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = libAtmosphere.a
+
+libAtmosphere_a_SOURCES = FGMSIS.cpp FGMSISData.cpp FGMars.cpp
+
+noinst_HEADERS = FGMSIS.h FGMars.h
+
+INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
diff --git a/src/FDM/JSBSim/models/flight_control/FGCondition.cpp b/src/FDM/JSBSim/models/flight_control/FGCondition.cpp
new file mode 100644 (file)
index 0000000..21adb3a
--- /dev/null
@@ -0,0 +1,295 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGCondition.cpp
+ Author:       Jon S. Berndt
+ Date started: 1/2/2003
+
+ -------------- Copyright (C) 2003 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGCondition.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_CONDITION;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+string FGCondition::indent = "        ";
+
+
+FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) :
+  PropertyManager(PropertyManager), isGroup(true)
+{
+  string property1, property2, logic;
+  Element* condition_element;
+
+  InitializeConditionals();
+
+  TestParam1  = TestParam2 = 0L;
+  TestValue   = 0.0;
+  Comparison  = ecUndef;
+  Logic       = elUndef;
+  conditions.clear();
+
+  logic = element->GetAttributeValue("logic");
+  if (logic == "OR") Logic = eOR;
+  else if (logic == "AND") Logic = eAND;
+  else { // error
+    cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << logic << endl;
+  }
+  condition_element = element->GetElement();
+  while (condition_element) {
+    conditions.push_back(FGCondition(condition_element, PropertyManager));
+    condition_element = element->GetNextElement();
+  }
+  for (int i=0; i<element->GetNumDataLines(); i++) {
+    conditions.push_back(FGCondition(element->GetDataLine(i), PropertyManager));
+  }
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) :
+  PropertyManager(PropertyManager), isGroup(false)
+{
+  string property1, property2, compare_string;
+  Element* condition_element;
+
+  InitializeConditionals();
+
+  TestParam1  = TestParam2 = 0L;
+  TestValue   = 0.0;
+  Comparison  = ecUndef;
+  Logic       = elUndef;
+  conditions.clear();
+
+  int start = 0, end = 0;
+  start = test.find_first_not_of(" ");
+  end = test.find_first_of(" ", start+1);
+  property1 = test.substr(start,end-start);
+  start = test.find_first_not_of(" ",end);
+  end = test.find_first_of(" ",start+1);
+  conditional = test.substr(start,end-start);
+  start = test.find_first_not_of(" ",end);
+  end = test.find_first_of(" ",start+1);
+  property2 = test.substr(start,end-start);
+
+  TestParam1 = PropertyManager->GetNode(property1, true);
+  Comparison = mComparison[conditional];
+  if (property2.find_first_not_of("-.0123456789eE") == string::npos) {
+    TestValue = atof(property2.c_str());
+  } else {
+    TestParam2 = PropertyManager->GetNode(property2, true);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGCondition::InitializeConditionals(void)
+{
+  mComparison["EQ"] = eEQ;
+  mComparison["NE"] = eNE;
+  mComparison["GT"] = eGT;
+  mComparison["GE"] = eGE;
+  mComparison["LT"] = eLT;
+  mComparison["LE"] = eLE;
+  mComparison["eq"] = eEQ;
+  mComparison["ne"] = eNE;
+  mComparison["gt"] = eGT;
+  mComparison["ge"] = eGE;
+  mComparison["lt"] = eLT;
+  mComparison["le"] = eLE;
+  mComparison["=="] = eEQ;
+  mComparison["!="] = eNE;
+  mComparison[">"]  = eGT;
+  mComparison[">="] = eGE;
+  mComparison["<"]  = eLT;
+  mComparison["<="] = eLE;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGCondition::~FGCondition(void)
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGCondition::Evaluate(void )
+{
+  vector <FGCondition>::iterator iConditions;
+  bool pass = false;
+  double compareValue;
+
+  if (Logic == eAND) {
+
+    iConditions = conditions.begin();
+    pass = true;
+    while (iConditions < conditions.end()) {
+      if (!iConditions->Evaluate()) pass = false;
+      *iConditions++;
+    }
+
+  } else if (Logic == eOR) {
+
+    pass = false;
+    while (iConditions < conditions.end()) {
+      if (iConditions->Evaluate()) pass = true;
+      *iConditions++;
+    }
+
+  } else {
+
+    if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue();
+    else compareValue = TestValue;
+
+    switch (Comparison) {
+    case ecUndef:
+      cerr << "Undefined comparison operator." << endl;
+      break;
+    case eEQ:
+      pass = TestParam1->getDoubleValue() == compareValue;
+      break;
+    case eNE:
+      pass = TestParam1->getDoubleValue() != compareValue;
+      break;
+    case eGT:
+      pass = TestParam1->getDoubleValue() > compareValue;
+      break;
+    case eGE:
+      pass = TestParam1->getDoubleValue() >= compareValue;
+      break;
+    case eLT:
+      pass = TestParam1->getDoubleValue() < compareValue;
+      break;
+    case eLE:
+      pass = TestParam1->getDoubleValue() <= compareValue;
+      break;
+    default:
+     cerr << "Unknown comparison operator." << endl;
+    }
+  }
+
+  return pass;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGCondition::PrintCondition(void )
+{
+  vector <FGCondition>::iterator iConditions;
+  string scratch;
+
+  if (isGroup) {
+    switch(Logic) {
+    case (elUndef):
+      scratch = " UNSET";
+      cerr << "unset logic for test condition" << endl;
+      break;
+    case (eAND):
+      scratch = " if all of the following are true";
+      break;
+    case (eOR):
+      scratch = " if any of the following are true:";
+      break;
+    default:
+      scratch = " UNKNOWN";
+      cerr << "Unknown logic for test condition" << endl;
+    }
+
+    iConditions = conditions.begin();
+    cout << scratch << endl;
+    while (iConditions < conditions.end()) {
+      iConditions->PrintCondition();
+      *iConditions++;
+    }
+  } else {
+    if (TestParam2 != 0L)
+      cout << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName();
+    else
+      cout << TestParam1->GetName() << " " << conditional << " " << TestValue;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGCondition::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: FGCondition" << endl;
+    if (from == 1) cout << "Destroyed:    FGCondition" << 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;
+    }
+  }
+}
+
+} //namespace JSBSim
+
diff --git a/src/FDM/JSBSim/models/flight_control/FGCondition.h b/src/FDM/JSBSim/models/flight_control/FGCondition.h
new file mode 100644 (file)
index 0000000..fbb643b
--- /dev/null
@@ -0,0 +1,99 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGCondition.h
+ Author:       Jon S. Berndt
+ Date started: 1/02/2003
+
+ ------------- Copyright (C)  -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGCONDITION_H
+#define FGCONDITION_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <map>
+#include <FGJSBBase.h>
+#include <input_output/FGXMLElement.h>
+#include <input_output/FGPropertyManager.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_CONDITION "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a condition, which is used in parts of JSBSim including switches
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGCondition : public FGJSBBase
+{
+public:
+  FGCondition(Element* element, FGPropertyManager* PropertyManager);
+  FGCondition(string test, FGPropertyManager* PropertyManager);
+  ~FGCondition(void);
+
+  bool Evaluate(void);
+  void PrintCondition(void);
+
+private:
+  enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE};
+  enum eLogic {elUndef=0, eAND, eOR};
+  map <string, eComparison> mComparison;
+  eLogic Logic;
+
+  FGPropertyManager *TestParam1, *TestParam2, *PropertyManager;
+  double TestValue;
+  eComparison Comparison;
+  bool isGroup;
+  string conditional;
+
+  static string indent;
+
+  vector <FGCondition> conditions;
+  void InitializeConditionals(void);
+
+  void Debug(int from);
+};
+}
+#endif
+
diff --git a/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp b/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp
new file mode 100644 (file)
index 0000000..bbd8f68
--- /dev/null
@@ -0,0 +1,148 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGDeadBand.cpp
+ Author:       Jon S. Berndt
+ Date started: 11/1999
+
+ ------------- Copyright (C) 2000 -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGDeadBand.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_DEADBAND;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  gain = 1.0;
+  width = 0.0;
+
+  if (element->FindElement("width")) {
+    width = element->FindElementValueAsNumber("width");
+  }
+
+  if (element->FindElement("gain")) {
+    gain = element->FindElementValueAsNumber("gain");
+  }
+
+  FGFCSComponent::bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGDeadBand::~FGDeadBand()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGDeadBand::Run(void )
+{
+  Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
+
+  if (Input < -width/2.0) {
+    Output = (Input + width/2.0)*gain;
+  } else if (Input > width/2.0) {
+    Output = (Input - width/2.0)*gain;
+  } else {
+    Output = 0.0;
+  }
+
+  Clip();
+
+  if (IsOutput) SetOutput();
+
+  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 FGDeadBand::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+      cout << "      DEADBAND WIDTH: " << width << endl;
+      cout << "      GAIN: " << gain << endl;
+      if (clip) cout << "      CLIPTO: " << clipmin
+                                  << ", " << clipmax << endl;
+      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGDeadBand" << endl;
+    if (from == 1) cout << "Destroyed:    FGDeadBand" << 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/models/flight_control/FGDeadBand.h b/src/FDM/JSBSim/models/flight_control/FGDeadBand.h
new file mode 100644 (file)
index 0000000..f94087c
--- /dev/null
@@ -0,0 +1,101 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGDeadBand.h
+ Author:       Jon Berndt
+ Date started: 2001
+
+ ------------- Copyright (C) 2001 Jon S. Berndt -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGDEADBAND_H
+#define FGDEADBAND_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_DEADBAND "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models a deadband object.
+    Here is the format of the deadband control specification:
+    <pre>
+    \<COMPONENT NAME="Deadbeat1" TYPE="DEADBAND">
+       INPUT {input}
+       WIDTH {deadband width}
+       MIN {minimum value}
+       MAX {maximum value}
+       [GAIN {optional deadband gain}]
+       [OUTPUT {optional output parameter to set}]
+    \</COMPONENT>
+    </pre>
+    The WIDTH value is the total deadband region within which an input will
+    produce no output. For example, say that the WIDTH value is 2.0.  If the
+    input is between -1.0 and +1.0, the output will be zero.
+    @author Jon S. Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGDeadBand  : public FGFCSComponent
+{
+public:
+  FGDeadBand(FGFCS* fcs, Element* element);
+  ~FGDeadBand();
+
+  bool Run(void);
+
+private:
+  double width;
+  double gain;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
new file mode 100644 (file)
index 0000000..d103b20
--- /dev/null
@@ -0,0 +1,245 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGFCSComponent.cpp
+ Author:       Jon S. Berndt
+ Date started: 11/1999
+
+ ------------- Copyright (C) 2000 -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSComponent.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FCSCOMPONENT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
+{
+  Element *input_element, *clip_el;
+  Input = Output = clipmin = clipmax = 0.0;
+  OutputNode = treenode = 0;
+  ClipMinPropertyNode = ClipMaxPropertyNode = 0;
+  IsOutput   = clip = false;
+  string input, clip_string;
+
+  PropertyManager = fcs->GetPropertyManager();
+  Type = element->GetAttributeValue("type"); // Old, deprecated format
+  if (Type.empty()) {
+    if        (element->GetName() == string("lag_filter")) {
+      Type = "LAG_FILTER";
+    } else if (element->GetName() == string("lead_lag_filter")) {
+      Type = "LEAD_LAG_FILTER";
+    } else if (element->GetName() == string("washout_filter")) {
+      Type = "WASHOUT_FILTER";
+    } else if (element->GetName() == string("second_order_filter")) {
+      Type = "SECOND_ORDER_FILTER";
+    } else if (element->GetName() == string("integrator")) {
+      Type = "INTEGRATOR";
+    } else if (element->GetName() == string("summer")) {
+      Type = "SUMMER";
+    } else if (element->GetName() == string("pure_gain")) {
+      Type = "PURE_GAIN";
+    } else if (element->GetName() == string("scheduled_gain")) {
+      Type = "SCHEDULED_GAIN";
+    } else if (element->GetName() == string("aerosurface_scale")) {
+      Type = "AEROSURFACE_SCALE";
+    } else if (element->GetName() == string("switch")) {
+      Type = "SWITCH";
+    } else if (element->GetName() == string("kinematic")) {
+      Type = "KINEMATIC";
+    } else if (element->GetName() == string("deadband")) {
+      Type = "DEADBAND";
+    } else if (element->GetName() == string("fcs_function")) {
+      Type = "FCS_FUNCTION";
+    } else if (element->GetName() == string("sensor")) {
+      Type = "SENSOR";
+    } else { // illegal component in this channel
+      Type = "UNKNOWN";
+    }
+  }
+
+  Name = element->GetAttributeValue("name");
+
+  input_element = element->FindElement("input");
+  while (input_element) {
+    input = input_element->GetDataLine();
+    if (input[0] == '-') {
+      InputSigns.push_back(-1.0);
+      input.erase(0,1);
+    } else {
+      InputSigns.push_back( 1.0);
+    }
+    InputNodes.push_back( resolveSymbol(input) );
+    input_element = element->FindNextElement("input");
+  }
+
+  if (element->FindElement("output")) {
+    IsOutput = true;
+    OutputNode = PropertyManager->GetNode( element->FindElementValue("output") );
+    if (!OutputNode) {
+      cerr << endl << "  Unable to process property: " << element->FindElementValue("output") << endl;
+      throw(string("Invalid output property name in flight control definition"));
+    }
+  }
+
+  clip_el = element->FindElement("clipto");
+  if (clip_el) {
+    clip_string = clip_el->FindElementValue("min");
+    if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property
+      ClipMinPropertyNode = PropertyManager->GetNode( clip_string );
+    } else {
+      clipmin = clip_el->FindElementValueAsNumber("min");
+    }
+    clip_string = clip_el->FindElementValue("max");
+    if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property
+      ClipMaxPropertyNode = PropertyManager->GetNode( clip_string );
+    } else {
+      clipmax = clip_el->FindElementValueAsNumber("max");
+    }
+    clip = true;
+  }
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGFCSComponent::~FGFCSComponent()
+{
+//  string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
+//  PropertyManager->Untie( tmp);
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCSComponent::SetOutput(void)
+{
+  OutputNode->setDoubleValue(Output);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGFCSComponent::Run(void)
+{
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCSComponent::Clip(void)
+{
+  if (clip) {
+    if (ClipMinPropertyNode != 0) clipmin = ClipMinPropertyNode->getDoubleValue();
+    if (ClipMaxPropertyNode != 0) clipmax = ClipMaxPropertyNode->getDoubleValue();
+    if (Output > clipmax)      Output = clipmax;
+    else if (Output < clipmin) Output = clipmin;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPropertyManager* FGFCSComponent::resolveSymbol(string token)
+{
+  string prop;
+  FGPropertyManager* tmp = PropertyManager->GetNode(token,false);
+  if (!tmp) {
+    if (token.find("/") == token.npos) prop = "model/" + token;
+    cerr << "Creating new property " << prop << endl;
+    tmp = PropertyManager->GetNode(token,true);
+  }
+  return tmp;
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFCSComponent::bind(void)
+{
+  string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
+  PropertyManager->Tie( tmp, this, &FGFCSComponent::GetOutput);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGFCSComponent::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) {
+      cout << endl << "    Loading Component \"" << Name
+                   << "\" of type: " << Type << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGFCSComponent" << endl;
+    if (from == 1) cout << "Destroyed:    FGFCSComponent" << 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/models/flight_control/FGFCSComponent.h b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
new file mode 100644 (file)
index 0000000..eb5bf1b
--- /dev/null
@@ -0,0 +1,137 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGFCSComponent.h
+ Author:       Jon S. Berndt
+ Date started: 05/01/2000
+
+ ------------- Copyright (C)  -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGFCSCOMPONENT_H
+#define FGFCSCOMPONENT_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#endif
+
+#include <string>
+#include <vector>
+#include <FGJSBBase.h>
+#include <input_output/FGPropertyManager.h>
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FCSCOMPONENT "$Id$"
+
+using std::string;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Base class for JSBSim Flight Control System Components.
+    The Flight Control System (FCS) for JSBSim consists of the FCS container
+    class (see \URL[FGFCS]{FGFCS.html}), the FGFCSComponent base class, and the
+    component classes from which can be constructed a string, or channel. See:
+
+    - FGSwitch
+    - FGGain
+    - FGKinemat
+    - FGFilter
+    - FGDeadBand
+    - FGSummer
+    - FGGradient
+
+    @author Jon S. Berndt
+    @version $Id$
+    @see Documentation for the FGFCS class, and for the configuration file class
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGFCSComponent : public FGJSBBase
+{
+public:
+  /// Constructor
+  FGFCSComponent(FGFCS* fcs, Element* el);
+  /// Destructor
+  virtual ~FGFCSComponent();
+
+  virtual bool Run(void);
+  virtual void SetOutput(void);
+  inline double GetOutput (void) const {return Output;}
+  inline FGPropertyManager* GetOutputNode(void) { return OutputNode; }
+  inline string GetName(void) const {return Name;}
+  inline string GetType(void) const { return Type; }
+  virtual double GetOutputPct(void) const { return 0; }
+
+protected:
+  FGFCS* fcs;
+  FGPropertyManager* PropertyManager;
+  FGPropertyManager* treenode;
+  FGPropertyManager* OutputNode;
+  FGPropertyManager* ClipMinPropertyNode;
+  FGPropertyManager* ClipMaxPropertyNode;
+  vector <FGPropertyManager*> InputNodes;
+  vector <float> InputSigns;
+  string Type;
+  string Name;
+  double Input;
+  double Output;
+  double clipmax, clipmin;
+  bool IsOutput;
+  bool clip;
+
+  void Clip(void);
+  virtual void bind();
+  FGPropertyManager* resolveSymbol(string token);
+
+  virtual void Debug(int from);
+};
+
+} //namespace JSBSim
+
+#include "../FGFCS.h"
+
+#endif
+
diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp
new file mode 100755 (executable)
index 0000000..4c19f4e
--- /dev/null
@@ -0,0 +1,138 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGFCSFunction.cpp
+ Author:       Jon S. Berndt
+ Date started: 6/2005
+
+ ------------- Copyright (C) 2005 -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSFunction.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FCSFUNCTION;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGFCSFunction::FGFCSFunction(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  Element *function_element = element->FindElement("function");
+
+  function = new FGFunction(PropertyManager, function_element);
+
+  FGFCSComponent::bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGFCSFunction::~FGFCSFunction()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGFCSFunction::Run(void )
+{
+  Output = function->GetValue();
+
+  if (InputNodes.size() > 0) {
+    Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
+    Output*= Input;
+  }
+
+  Clip();
+
+  if (IsOutput) SetOutput();
+
+  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 FGFCSFunction::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      if (InputNodes.size()>0)
+        cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+//    cout << "      Function: " << endl;
+      if (clip) cout << "      CLIPTO: " << clipmin
+                                  << ", " << clipmax << endl;
+      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGFCSFunction" << endl;
+    if (from == 1) cout << "Destroyed:    FGFCSFunction" << 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/models/flight_control/FGFCSFunction.h b/src/FDM/JSBSim/models/flight_control/FGFCSFunction.h
new file mode 100755 (executable)
index 0000000..9f1c531
--- /dev/null
@@ -0,0 +1,87 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGFCSFunction.h
+ Author:       Jon Berndt
+ Date started: 2005
+
+ ------------- Copyright (C) 2005 Jon S. Berndt -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGFCSFUNCTION_H
+#define FGFCSFUNCTION_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+#include <math/FGFunction.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FCSFUNCTION "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models a FCSFunction object.
+    @author Jon S. Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGFCSFunction  : public FGFCSComponent
+{
+public:
+  FGFCSFunction(FGFCS* fcs, Element* element);
+  ~FGFCSFunction();
+
+  bool Run(void);
+
+private:
+  FGFunction* function;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/FGFilter.cpp b/src/FDM/JSBSim/models/flight_control/FGFilter.cpp
new file mode 100644 (file)
index 0000000..79ec7e1
--- /dev/null
@@ -0,0 +1,229 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFilter.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FILTER;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGFilter::FGFilter(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  double denom;
+
+  dt = fcs->GetState()->Getdt();
+  Trigger = 0;
+
+  C1 = C2 = C3 = C4 = C5 = C6 = 0.0;
+
+  if      (Type == "LAG_FILTER")          FilterType = eLag        ;
+  else if (Type == "LEAD_LAG_FILTER")     FilterType = eLeadLag    ;
+  else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2     ;
+  else if (Type == "WASHOUT_FILTER")      FilterType = eWashout    ;
+  else if (Type == "INTEGRATOR")          FilterType = eIntegrator ;
+  else                                    FilterType = eUnknown    ;
+
+  if (element->FindElement("c1")) C1 = element->FindElementValueAsNumber("c1");
+  if (element->FindElement("c2")) C2 = element->FindElementValueAsNumber("c2");
+  if (element->FindElement("c3")) C3 = element->FindElementValueAsNumber("c3");
+  if (element->FindElement("c4")) C4 = element->FindElementValueAsNumber("c4");
+  if (element->FindElement("c5")) C5 = element->FindElementValueAsNumber("c5");
+  if (element->FindElement("c6")) C6 = element->FindElementValueAsNumber("c6");
+  if (element->FindElement("trigger")) {
+    Trigger =  resolveSymbol(element->FindElementValue("trigger"));
+  }
+
+  Initialize = true;
+
+  switch (FilterType) {
+    case eLag:
+      denom = 2.00 + dt*C1;
+      ca = dt*C1 / denom;
+      cb = (2.00 - dt*C1) / denom;
+      break;
+    case eLeadLag:
+      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*C4) / denom;
+      break;
+    case eOrder2:
+      denom = 4.0*C4 + 2.0*C5*dt + C6*dt*dt;
+      ca = (4.0*C1 + 2.0*C2*dt + C3*dt*dt) / denom;
+      cb = (2.0*C3*dt*dt - 8.0*C1) / denom;
+      cc = (4.0*C1 - 2.0*C2*dt + C3*dt*dt) / denom;
+      cd = (2.0*C6*dt*dt - 8.0*C4) / denom;
+      ce = (4.0*C4 - 2.0*C5*dt + C6*dt*dt) / denom;
+      break;
+    case eWashout:
+      denom = 2.00 + dt*C1;
+      ca = 2.00 / denom;
+      cb = (2.00 - dt*C1) / denom;
+      break;
+    case eIntegrator:
+      ca = dt*C1 / 2.00;
+      break;
+    case eUnknown:
+      cerr << "Unknown filter type" << endl;
+    break;
+  }
+  FGFCSComponent::bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGFilter::~FGFilter()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGFilter::Run(void)
+{
+  double test = 0.0;
+
+  if (Initialize) {
+
+    PreviousOutput1 = PreviousInput1 = Output = Input;
+    Initialize = false;
+
+  } else {
+
+    Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
+    switch (FilterType) {
+      case eLag:
+        Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb;
+        break;
+      case eLeadLag:
+        Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc;
+        break;
+      case eOrder2:
+        Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc
+                            - PreviousOutput1 * cd - PreviousOutput2 * ce;
+        break;
+      case eWashout:
+        Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
+        break;
+      case eIntegrator:
+        if (Trigger != 0) {
+          test = Trigger->getDoubleValue();
+          if (fabs(test) > 0.000001) {
+            Input  = PreviousInput1 = PreviousInput2 = 0.0;
+          }
+        }
+        Output = Input * ca + PreviousInput1 * ca + PreviousOutput1;
+        break;
+      case eUnknown:
+        break;
+    }
+
+  }
+
+  PreviousOutput2 = PreviousOutput1;
+  PreviousOutput1 = Output;
+  PreviousInput2  = PreviousInput1;
+  PreviousInput1  = Input;
+
+  Clip();
+  if (IsOutput) SetOutput();
+
+  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 FGFilter::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+      cout << "      C1: " << C1 << endl;
+      cout << "      C2: " << C2 << endl;
+      cout << "      C3: " << C3 << endl;
+      cout << "      C4: " << C4 << endl;
+      cout << "      C5: " << C5 << endl;
+      cout << "      C6: " << C6 << endl;
+      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGFilter" << endl;
+    if (from == 1) cout << "Destroyed:    FGFilter" << 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/models/flight_control/FGFilter.h b/src/FDM/JSBSim/models/flight_control/FGFilter.h
new file mode 100644 (file)
index 0000000..694018e
--- /dev/null
@@ -0,0 +1,223 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGFilter.h
+ Author:       Jon S. Berndt
+ Date started: 4/2000
+
+ ------------- Copyright (C)  -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGFILTER_H
+#define FGFILTER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FILTER "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a filter for the flight control system.
+The filter component can simulate any filter up to second order. The
+Tustin substitution is used to take filter definitions from LaPlace space to the
+time domain. The general format for a filter specification is:
+
+<pre>
+\<component name="name" type="type">
+  \<input> property \</input>
+  \<c1> value \<c/1>
+  [\<c2> value \<c/2>]
+  [\<c3> value \<c/3>]
+  [\<c4> value \<c/4>]
+  [\<c5> value \<c/5>]
+  [\<c6> value \<c/6>]
+  [\<output> property \<output>]
+\</component>
+</pre>
+
+For a lag filter of the form,
+<pre>
+  C1
+------
+s + C1
+</pre>
+the corresponding filter definition is:
+<pre>
+\<component name="name" type="LAG_FILTER">
+  \<input> property \</input>
+  \<c1> value \<c/1>
+  [\<output> property \<output>]
+\</component>
+</pre>
+As an example, for the specific filter:
+<pre>
+  600
+------
+s + 600
+</pre>
+the corresponding filter definition could be:
+<pre>
+\<component name="Heading Roll Error Lag" type="LAG_FILTER">
+  \<input> fcs/heading-command \</input>
+  \<c1> 600 \</c1>
+\</component>
+</pre>
+For a lead-lag filter of the form:
+<pre>
+C1*s + C2
+---------
+C3*s + C4
+</pre>
+The corresponding filter definition is:
+<pre>
+\<component name="name" type="LEAD_LAG_FILTER">
+  \<input> property \</input>
+  \<c1> value \<c/1>
+  \<c2> value \<c/2>
+  \<c3> value \<c/3>
+  \<c4> value \<c/4>
+  [\<output> property \<output>]
+\</component>
+</pre>
+For a washout filter of the form:
+<pre>
+  s
+------
+s + C1
+</pre>
+The corresponding filter definition is:
+<pre>
+\<component name="name" type="WASHOUT_FILTER">
+  \<input> property \</input>
+  \<c1> value \</c1>
+  [\<output> property \<output>]
+\</component>
+</pre>
+For a second order filter of the form:
+<pre>
+C1*s^2 + C2*s + C3
+------------------
+C4*s^2 + C5*s + C6
+</pre>
+The corresponding filter definition is:
+<pre>
+\<component name="name" type="SECOND_ORDER_FILTER">
+  \<input> property \</input>
+  \<c1> value \<c/1>
+  \<c2> value \<c/2>
+  \<c3> value \<c/3>
+  \<c4> value \<c/4>
+  \<c5> value \<c/5>
+  \<c6> value \<c/6>
+  [\<output> property \<output>]
+\</component>
+</pre>
+For an integrator of the form:
+<pre>
+ C1
+ ---
+  s
+</pre>
+The corresponding filter definition is:
+<pre>
+\<component name="name" type="INTEGRATOR">
+  \<input> property \</input>
+  \<c1> value \<c/1>
+  [\<trigger> property \</trigger>]
+  [\<output> property \<output>]
+\</component>
+</pre>
+For the integrator, the trigger features the following behavior. If the trigger
+property value is:
+  - 0: no action is taken - the output is calculated normally
+  - not 0: (or simply greater than zero), all current and previous inputs will
+           be set to 0.0
+
+In all the filter specifications above, an \<output> element is also seen.  This
+is so that the last component in a "string" can copy its value to the appropriate
+output, such as the elevator, or speedbrake, etc.
+
+@author Jon S. Berndt
+@version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGFilter  : public FGFCSComponent
+{
+public:
+  FGFilter(FGFCS* fcs, Element* element);
+  ~FGFilter();
+
+  bool Run (void);
+
+  /** When true, causes previous values to be set to current values. This
+      is particularly useful for first pass. */
+  bool Initialize;
+
+  enum {eLag, eLeadLag, eOrder2, eWashout, eIntegrator, eUnknown} FilterType;
+
+private:
+  double dt;
+  double ca;
+  double cb;
+  double cc;
+  double cd;
+  double ce;
+  double C1;
+  double C2;
+  double C3;
+  double C4;
+  double C5;
+  double C6;
+  double PreviousInput1;
+  double PreviousInput2;
+  double PreviousOutput1;
+  double PreviousOutput2;
+  FGPropertyManager* Trigger;
+  void Debug(int from);
+};
+}
+#endif
+
diff --git a/src/FDM/JSBSim/models/flight_control/FGGain.cpp b/src/FDM/JSBSim/models/flight_control/FGGain.cpp
new file mode 100644 (file)
index 0000000..b46e772
--- /dev/null
@@ -0,0 +1,234 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGGain.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_GAIN;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  Element *scale_element, *zero_centered;
+  string strScheduledBy, gain_string, sZeroCentered;
+
+  GainPropertyNode = 0;
+  Gain = 1.000;
+  Rows = 0;
+  Table = 0;
+  InMin = -1.0;
+  InMax =  1.0;
+  OutMin = OutMax = 0.0;
+
+  if (Type == "PURE_GAIN") {
+    if ( !element->FindElement("gain") ) {
+      cout << highint << "      No GAIN specified (default: 1.0)" << normint << endl;
+    }
+  }
+
+  if ( element->FindElement("gain") ) {
+    gain_string = element->FindElementValue("gain");
+    if (gain_string.find_first_not_of("+-.0123456789") != string::npos) { // property
+      GainPropertyNode = PropertyManager->GetNode(gain_string);
+    } else {
+      Gain = element->FindElementValueAsNumber("gain");
+    }
+  }
+
+  if (Type == "AEROSURFACE_SCALE") {
+    scale_element = element->FindElement("domain");
+    if (scale_element) {
+      if (scale_element->FindElement("max") && scale_element->FindElement("min") )
+      {
+        InMax = scale_element->FindElementValueAsNumber("max");
+        InMin = scale_element->FindElementValueAsNumber("min");
+      }
+    }
+    scale_element = element->FindElement("range");
+    if (!scale_element) throw(string("No range supplied for aerosurface scale component"));
+    if (scale_element->FindElement("max") && scale_element->FindElement("min") )
+    {
+      OutMax = scale_element->FindElementValueAsNumber("max");
+      OutMin = scale_element->FindElementValueAsNumber("min");
+    } else {
+      cerr << "Maximum and minimum output values must be supplied for the "
+              "aerosurface scale component" << endl;
+      exit(-1);
+    }
+    ZeroCentered = true;
+    zero_centered = element->FindElement("zero_centered");
+    if (zero_centered) {
+      sZeroCentered = zero_centered->FindElementValue("zero_centered");
+      if (sZeroCentered == string("0") || sZeroCentered == string("false")) {
+        ZeroCentered = false;
+      }
+    }
+  }
+
+  if (Type == "SCHEDULED_GAIN") {
+    if (element->FindElement("table")) {
+      Table = new FGTable(PropertyManager, element->FindElement("table"));
+    } else {
+      cerr << "A table must be provided for the scheduled gain component" << endl;
+      exit(-1);
+    }
+  }
+
+  FGFCSComponent::bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGGain::~FGGain()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGGain::Run(void )
+{
+  double SchedGain = 1.0;
+
+  Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
+
+  if (GainPropertyNode != 0) Gain = GainPropertyNode->getDoubleValue();
+
+  if (Type == "PURE_GAIN") {                       // PURE_GAIN
+
+    Output = Gain * Input;
+
+  } else if (Type == "SCHEDULED_GAIN") {           // SCHEDULED_GAIN
+
+    SchedGain = Table->GetValue();
+    Output = Gain * SchedGain * Input;
+
+  } else if (Type == "AEROSURFACE_SCALE") {        // AEROSURFACE_SCALE
+
+    if (ZeroCentered) {
+      if (Input == 0.0) {
+        Output = 0.0;
+      } else if (Input > 0) {
+        Output = (Input / InMax) * OutMax;
+      } else {
+        Output = (Input / InMin) * OutMin;
+      }
+    } else {
+      Output = OutMin + ((Input - InMin) / (InMax - InMin)) * (OutMax - OutMin);
+    }
+
+    Output *= Gain;
+  }
+
+  Clip();
+  if (IsOutput) SetOutput();
+
+  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 FGGain::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      if (InputSigns[0] < 0)
+        cout << "      INPUT: -" << InputNodes[0]->getName() << endl;
+      else
+        cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+
+      cout << "      GAIN: " << Gain << endl;
+      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
+      if (Type == "AEROSURFACE_SCALE") {
+        cout << "      In/Out Mapping:" << endl;
+        cout << "        Input MIN: " << InMin << endl;
+        cout << "        Input MAX: " << InMax << endl;
+        cout << "        Output MIN: " << OutMin << endl;
+        cout << "        Output MAX: " << OutMax << endl;
+      }
+      if (Table != 0) {
+        cout << "      Scheduled by table: " << endl;
+        Table->Print();
+      }
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGGain" << endl;
+    if (from == 1) cout << "Destroyed:    FGGain" << 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/models/flight_control/FGGain.h b/src/FDM/JSBSim/models/flight_control/FGGain.h
new file mode 100644 (file)
index 0000000..778ad03
--- /dev/null
@@ -0,0 +1,188 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGGain.h
+ Author:
+ Date started:
+
+ ------------- Copyright (C)  -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGGAIN_H
+#define FGGAIN_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_STRING
+   SG_USING_STD(string);
+#else
+#  include <string>
+#endif
+
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+#include <math/FGTable.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_GAIN "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a gain component for the flight control system.
+    The gain component merely multiplies the input by a gain.  The form of the
+    gain component specification is:
+    <pre>
+    \<component name="name" type="PURE_GAIN">
+      \<input> property \</input>
+      \<gain> value \</gain>
+      [\<output> property \</output>]
+    \</component>
+    </pre>
+    Note: as is the case with the Summer component, the input property name may be
+    immediately preceded by a minus sign to invert that signal.
+
+    The scheduled gain component multiplies the input by a variable gain that is
+    dependent on another property (such as qbar, altitude, etc.).  The lookup
+    mapping is in the form of a table.  This kind of component might be used, for
+    example, in a case where aerosurface deflection must only be commanded to
+    acceptable settings - i.e at higher qbar the commanded elevator setting might
+    be attenuated.  The form of the scheduled gain component specification is:
+    <pre>
+    \<COMPONENT NAME="name" TYPE="SCHEDULED_GAIN">
+      INPUT \<property>
+      [GAIN  \<value>]
+      SCHEDULED_BY \<property>
+      ROWS \<number_of_rows>
+      \<lookup_value  gain_value>
+      ?
+      [CLIPTO \<min> \<max> 1]
+      [OUTPUT \<property>]
+    \</COMPONENT>
+    </pre>
+    An overall GAIN may be supplied that is multiplicative with the scheduled gain.
+
+    Note: as is the case with the Summer component, the input property name may
+    be immediately preceded by a minus sign to invert that signal.
+
+    Here is an example of a scheduled gain component specification:
+    <pre>
+    \<COMPONENT NAME="Pitch Scheduled Gain 1" TYPE="SCHEDULED_GAIN">
+      INPUT        fcs/pitch-gain-1
+      GAIN         0.017
+      SCHEDULED_BY fcs/elevator-pos-rad
+      ROWS         22
+      -0.68  -26.548
+      -0.595 -20.513
+      -0.51  -15.328
+      -0.425 -10.993
+      -0.34   -7.508
+      -0.255  -4.873
+      -0.17   -3.088
+      -0.085  -2.153
+       0      -2.068
+       0.085  -2.833
+       0.102  -3.088
+       0.119  -3.377
+       0.136  -3.7
+       0.153  -4.057
+       0.17   -4.448
+       0.187  -4.873
+       0.272  -7.508
+       0.357 -10.993
+       0.442 -15.328
+       0.527 -20.513
+       0.612 -26.548
+       0.697 -33.433
+    \</COMPONENT>
+    </pre>
+    In the example above, we see the utility of the overall GAIN value in
+    effecting a degrees-to-radians conversion.
+
+    The aerosurface scale component is a modified version of the simple gain
+    component.  The normal purpose
+    for this component is to take control inputs that range from -1 to +1 or
+    from 0 to +1 and scale them to match the expected inputs to a flight control
+    system.  For instance, the normal and expected ability of a pilot to push or
+    pull on a control stick is about 50 pounds.  The input to the pitch channelb
+    lock diagram of a flight control system is in units of pounds.  Yet, the
+    joystick control input is usually in a range from -1 to +1.  The form of the
+    aerosurface scaling component specification is:
+<pre>
+    \<COMPONENT NAME="name" TYPE="AEROSURFACE_SCALE">
+      INPUT \<property>
+      MIN \<value>
+      MAX \<value>
+      [GAIN  \<value>]
+      [OUTPUT \<property>]
+    \</COMPONENT>
+</pre>
+    Note: as is the case with the Summer component, the input property name may be
+    immediately preceded by a minus sign to invert that signal.
+
+    @author Jon S. Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGGain  : public FGFCSComponent
+{
+public:
+  FGGain(FGFCS* fcs, Element* element);
+  ~FGGain();
+
+  bool Run (void);
+
+private:
+  FGTable* Table;
+  FGPropertyManager* GainPropertyNode;
+  double Gain;
+  double InMin, InMax, OutMin, OutMax;
+  int Rows;
+  bool ZeroCentered;
+
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/FGGradient.cpp b/src/FDM/JSBSim/models/flight_control/FGGradient.cpp
new file mode 100644 (file)
index 0000000..c42d9b9
--- /dev/null
@@ -0,0 +1,118 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGGradient.cpp
+ Author:
+ Date started:
+
+ ------------- Copyright (C) 2000 -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGGradient.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_GRADIENT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGGradient::FGGradient(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  FGFCSComponent::bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGGradient::~FGGradient()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGGradient::Run(void )
+{
+  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 FGGradient::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: FGGradient" << endl;
+    if (from == 1) cout << "Destroyed:    FGGradient" << 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/models/flight_control/FGGradient.h b/src/FDM/JSBSim/models/flight_control/FGGradient.h
new file mode 100644 (file)
index 0000000..b51dee5
--- /dev/null
@@ -0,0 +1,80 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGGradient.h
+ Author:       
+ Date started: 
+
+ ------------- Copyright (C)  -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGGRADIENT_H
+#define FGGRADIENT_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_GRADIENT "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a gradient component for the flight control system.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGGradient  : public FGFCSComponent
+{
+public:
+  FGGradient(FGFCS* fcs, Element* element);
+  ~FGGradient();
+
+  bool Run (void);
+
+private:
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp b/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp
new file mode 100644 (file)
index 0000000..dffcce7
--- /dev/null
@@ -0,0 +1,215 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGKinemat.cpp
+ Author:       Tony Peden, for flight control system authored by Jon S. Berndt
+ Date started: 12/02/01
+
+ ------------- Copyright (C) 2000 Anthony K. Peden -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <math.h>
+#include <float.h>
+
+#include "FGKinemat.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FLAPS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGKinemat::FGKinemat(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  Element *traverse_element, *setting_element;
+  double tmpDetent;
+  double tmpTime;
+
+  Detents.clear();
+  TransitionTimes.clear();
+
+  Output = OutputPct = 0;
+  DoScale = true;
+
+  if (element->FindElement("noscale")) DoScale = false;
+
+  traverse_element = element->FindElement("traverse");
+  setting_element = traverse_element->FindElement("setting");
+  while (setting_element) {
+    tmpDetent = setting_element->FindElementValueAsNumber("position");
+    tmpTime = setting_element->FindElementValueAsNumber("time");
+    Detents.push_back(tmpDetent);
+    TransitionTimes.push_back(tmpTime);
+    setting_element = traverse_element->FindNextElement("setting");
+  }
+  NumDetents = Detents.size();
+
+  if (NumDetents <= 1) {
+    cerr << "Kinematic component " << Name
+         << " must have more than 1 setting element" << endl;
+    exit(-1);
+  }
+
+  FGFCSComponent::bind();
+//  treenode->Tie("output-norm", this, &FGKinemat::GetOutputPct );
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGKinemat::~FGKinemat()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGKinemat::Run(void )
+{
+  double dt = fcs->GetState()->Getdt();
+
+  Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
+
+  if (DoScale) Input *= Detents[NumDetents-1];
+
+  if (IsOutput) Output = OutputNode->getDoubleValue();
+
+  if (Input < Detents[0])
+    Input = Detents[0];
+  else if (Detents[NumDetents-1] < Input)
+    Input = Detents[NumDetents-1];
+
+  // Process all detent intervals the movement traverses until either the
+  // final value is reached or the time interval has finished.
+  while ( 0.0 < dt && !EqualToRoundoff(Input, Output) ) {
+
+    // Find the area where Output is in
+    int ind;
+    for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind)
+      if (NumDetents <= ind)
+        break;
+
+    // A transition time of 0.0 means an infinite rate.
+    // The output is reached in one step
+    if (TransitionTimes[ind] <= 0.0) {
+      Output = Input;
+      break;
+    } else {
+      // Compute the rate in this area
+      double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind];
+      // Compute the maximum input value inside this area
+      double ThisInput = Input;
+      if (ThisInput < Detents[ind-1])   ThisInput = Detents[ind-1];
+      if (Detents[ind] < ThisInput)     ThisInput = Detents[ind];
+      // Compute the time to reach the value in ThisInput
+      double ThisDt = fabs((ThisInput-Output)/Rate);
+
+      // and clip to the timestep size
+      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;
+    }
+  }
+
+  OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]);
+
+  Clip();
+  if (IsOutput) SetOutput();
+
+  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 FGKinemat::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "      INPUT: " << InputNodes[0]->getName() << endl;
+      cout << "      DETENTS: " << NumDetents << endl;
+      for (int i=0;i<NumDetents;i++) {
+        cout << "        " << Detents[i] << " " << TransitionTimes[i] << endl;
+      }
+      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
+      if (!DoScale) cout << "      NOSCALE" << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGKinemat" << endl;
+    if (from == 1) cout << "Destroyed:    FGKinemat" << 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/models/flight_control/FGKinemat.h b/src/FDM/JSBSim/models/flight_control/FGKinemat.h
new file mode 100644 (file)
index 0000000..43508de
--- /dev/null
@@ -0,0 +1,115 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header:       FGKinemat.h
+ Author:       Tony Peden, for flight control system authored by Jon S. Berndt
+ Date started: 12/02/01 
+ ------------- Copyright (C) Anthony K. Peden -------------
+ 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
+--------------------------------------------------------------------------------
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGKinemat_H
+#define FGKinemat_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#  else
+#    include <vector.h>
+#  endif
+#else
+#  include <vector>
+#endif
+
+#include <string>
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FLAPS "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a kinematic component for the flight control system.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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, Element* element);
+
+  /** 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:
+  vector<double> Detents;
+  vector<double> TransitionTimes;
+  int NumDetents;
+  double OutputPct;
+  bool  DoScale;
+
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.cpp b/src/FDM/JSBSim/models/flight_control/FGSensor.cpp
new file mode 100755 (executable)
index 0000000..b2d541d
--- /dev/null
@@ -0,0 +1,264 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGSensor.cpp
+ Author:       Jon Berndt
+ Date started: 9 July 2005
+
+ ------------- Copyright (C) 2005 -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGSensor.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_SENSOR;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  double denom;
+  dt = fcs->GetState()->Getdt();
+
+  // inputs are read from the base class constructor
+
+  dt = fcs->GetState()->Getdt();
+
+  bits = quantized = divisions = 0;
+  PreviousInput = PreviousOutput = 0.0;
+  min = max = bias = noise_variance = lag = drift_rate = drift = span = 0.0;
+  granularity = 0.0;
+  noise_type = 0;
+  fail_low = fail_high = fail_stuck = false;
+
+  Element* quantization_element = element->FindElement("quantization");
+  if ( quantization_element) {
+    if ( quantization_element->FindElement("bits") ) {
+      bits = (int)quantization_element->FindElementValueAsNumber("bits");
+    }
+    divisions = (1<<bits);
+    if ( quantization_element->FindElement("min") ) {
+      min = quantization_element->FindElementValueAsNumber("min");
+    }
+    if ( quantization_element->FindElement("max") ) {
+      max = quantization_element->FindElementValueAsNumber("max");
+    }
+    span = max - min;
+    granularity = span/divisions;
+  }
+  if ( element->FindElement("bias") ) {
+    bias = element->FindElementValueAsNumber("bias");
+  }
+  if ( element->FindElement("drift_rate") ) {
+    drift_rate = element->FindElementValueAsNumber("drift_rate");
+  }
+  if ( element->FindElement("lag") ) {
+    lag = element->FindElementValueAsNumber("lag");
+    denom = 2.00 + dt*lag;
+    ca = dt*lag / denom;
+    cb = (2.00 - dt*lag) / denom;
+  }
+  if ( element->FindElement("noise") ) {
+    noise_variance = element->FindElementValueAsNumber("noise");
+    string variation = element->FindElement("noise")->GetAttributeValue("variation");
+    if (variation == "PERCENT") {
+      NoiseType = ePercent;
+    } else if (variation == "ABSOLUTE") {
+      NoiseType = eAbsolute;
+    } else {
+      NoiseType = ePercent;
+      cerr << "Unknown noise type in sensor: " << Name << endl;
+      cerr << "  defaulting to PERCENT." << endl;
+    }
+  }
+
+  FGFCSComponent::bind();
+  bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGSensor::~FGSensor()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGSensor::Run(void )
+{
+  Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
+
+  Output = Input; // perfect sensor
+
+  // Degrade signal as specified
+
+  if (fail_stuck) {
+    Output = PreviousOutput;
+    return true;
+  }
+
+  if (lag != 0.0)            Lag();       // models sensor lag
+  if (noise_variance != 0.0) Noise();     // models noise
+  if (drift_rate != 0.0)     Drift();     // models drift over time
+  if (bias != 0.0)           Bias();      // models a finite bias
+
+  if (fail_low)  Output = -HUGE_VAL;
+  if (fail_high) Output =  HUGE_VAL;
+
+  if (bits != 0)             Quantize();  // models quantization degradation
+//  if (delay != 0.0)          Delay();     // models system signal transport latencies
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGSensor::Noise(void)
+{
+  double random_value = ((double)rand()/(double)RAND_MAX) - 0.5;
+
+  switch( NoiseType ) {
+  case ePercent:
+    Output *= (1.0 + noise_variance*random_value);
+    break;
+
+  case eAbsolute:
+    Output += noise_variance*random_value;
+    break;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGSensor::Bias(void)
+{
+  Output += bias;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGSensor::Drift(void)
+{
+  drift += drift_rate*dt;
+  Output += drift;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGSensor::Quantize(void)
+{
+  if (Output < min) Output = min;
+  if (Output > max) Output = max;
+  double portion = Output - min;
+  quantized = (int)(portion/granularity);
+  Output = quantized*granularity + min;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGSensor::Lag(void)
+{
+  // "Output" on the right side of the "=" is the current frame input
+  Output = ca * (Output + PreviousInput) + PreviousOutput * cb;
+
+  PreviousOutput = Output;
+  PreviousInput  = Input;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGSensor::bind(void)
+{
+  string tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
+  const string tmp_low = tmp + "/malfunction/fail_low";
+  const string tmp_high = tmp + "/malfunction/fail_high";
+  const string tmp_stuck = tmp + "/malfunction/fail_stuck";
+
+  PropertyManager->Tie( tmp_low, this, &FGSensor::GetFailLow, &FGSensor::SetFailLow);
+  PropertyManager->Tie( tmp_high, this, &FGSensor::GetFailHigh, &FGSensor::SetFailHigh);
+  PropertyManager->Tie( tmp_stuck, this, &FGSensor::GetFailStuck, &FGSensor::SetFailStuck);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGSensor::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: FGSensor" << endl;
+    if (from == 1) cout << "Destroyed:    FGSensor" << 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/models/flight_control/FGSensor.h b/src/FDM/JSBSim/models/flight_control/FGSensor.h
new file mode 100755 (executable)
index 0000000..a21644a
--- /dev/null
@@ -0,0 +1,158 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGSensor.h
+ Author:       Jon Berndt
+ Date started: 9 July 2005
+
+ ------------- Copyright (C) 2005 -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGSENSOR_H
+#define FGSENSOR_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_SENSOR "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a Sensor component for the flight control system.
+
+Syntax:
+
+<sensor name=\94name\94 rate_group=\94name\94>
+  <input> property </input>
+  <lag> number </lag>
+  <noise variation=\94PERCENT|ABSOLUTE\94> number </noise>
+  <quantization name="name">
+    <bits> number </bits>
+    <min> number </min>
+    <max> number </max>
+  </quantization>
+  <drift_rate> number </drift_rate>
+  <bias> number </bias>
+</sensor>
+
+Example:
+
+<sensor name=\94aero/sensor/qbar\94 rate_group=\94HFCS\94>
+  <input> aero/qbar </input>
+  <lag> 0.5 </lag>
+  <noise variation=\94PERCENT\94> 2 </noise>
+  <quantization name="aero/sensor/quantized/qbar">
+    <bits> 12 </bits>
+    <min> 0 </min>
+    <max> 400 </max>
+  </quantization>
+  <bias> 0.5 </bias>
+</sensor>
+
+The only required element in the sensor definition is the input element. In that
+case, no degradation would be modeled, and the output would simply be the input.
+
+For noise, if the type is PERCENT, then the value supplied is understood to be a
+percentage variance. That is, if the number given is 0.05, the the variance is
+understood to be +/-0.05 percent maximum variance. So, the actual value for the sensor
+will be *anywhere* from 0.95 to 1.05 of the actual "perfect" value at any time -
+even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the delta
+time.
+
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGSensor  : public FGFCSComponent
+{
+public:
+  FGSensor(FGFCS* fcs, Element* element);
+  ~FGSensor();
+  
+  inline void SetFailLow(double val) {if (val > 0.0) fail_low = true; else fail_low = false;}
+  inline void SetFailHigh(double val) {if (val > 0.0) fail_high = true; else fail_high = false;}
+  inline void SetFailStuck(double val) {if (val > 0.0) fail_stuck = true; else fail_stuck = false;}
+
+  inline double GetFailLow(void) const {if (fail_low) return 1.0; else return 0.0;}
+  inline double GetFailHigh(void) const {if (fail_high) return 1.0; else return 0.0;}
+  inline double GetFailStuck(void) const {if (fail_stuck) return 1.0; else return 0.0;}
+
+  bool Run (void);
+
+private:
+  enum eNoiseType {ePercent=0, eAbsolute} NoiseType;
+  double dt;
+  double min, max;
+  double span;
+  double bias;
+  double drift_rate;
+  double drift;
+  double noise_variance;
+  double lag;
+  double granularity;
+  double ca; /// lag filter coefficient "a"
+  double cb; /// lag filter coefficient "b"
+  double PreviousOutput;
+  double PreviousInput;
+  int noise_type;
+  int bits;
+  int quantized;
+  int divisions;
+  bool fail_low;
+  bool fail_high;
+  bool fail_stuck;
+
+  void Noise(void);
+  void Bias(void);
+  void Drift(void);
+  void Quantize(void);
+  void Lag(void);
+
+  void bind(void);
+
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/FGSummer.cpp b/src/FDM/JSBSim/models/flight_control/FGSummer.cpp
new file mode 100644 (file)
index 0000000..06b575f
--- /dev/null
@@ -0,0 +1,146 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGSummer.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
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGSummer.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_SUMMER;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGSummer::FGSummer(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  Bias = 0.0;
+
+  if (element->FindElement("bias")) Bias = element->FindElementValueAsNumber("bias");
+
+  FGFCSComponent::bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGSummer::~FGSummer()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGSummer::Run(void )
+{
+  unsigned int idx;
+
+  Output = 0.0;
+
+  for (idx=0; idx<InputNodes.size(); idx++) {
+    Output += InputNodes[idx]->getDoubleValue() * InputSigns[idx];
+  }
+
+  Output += Bias;
+
+  Clip();
+  if (IsOutput) SetOutput();
+
+  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 FGSummer::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "      INPUTS: " << endl;
+      for (unsigned i=0;i<InputNodes.size();i++) {
+        if (InputSigns[i] < 0)
+          cout << "       -" << InputNodes[i]->getName() << endl;
+        else
+          cout << "       " << InputNodes[i]->getName() << endl;
+      }
+      if (Bias != 0.0) cout << "       Bias: " << Bias << endl;
+      if (clip) cout << "      CLIPTO: " << clipmin
+                                  << ", " << clipmax << endl;
+      if (IsOutput) cout << "      OUTPUT: " <<OutputNode->getName() <<  endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGSummer" << endl;
+    if (from == 1) cout << "Destroyed:    FGSummer" << 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;
+    }
+  }
+}
+
+} //namespace JSBSim
+
diff --git a/src/FDM/JSBSim/models/flight_control/FGSummer.h b/src/FDM/JSBSim/models/flight_control/FGSummer.h
new file mode 100644 (file)
index 0000000..ede4b26
--- /dev/null
@@ -0,0 +1,124 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGSummer.h
+ Author:
+ Date started:
+
+ ------------- Copyright (C)  -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGSUMMER_H
+#define FGSUMMER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#  else
+#    include <vector.h>
+#  endif
+#else
+#  include <vector>
+#endif
+
+#include <string>
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_SUMMER "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models a flight control system summing component.
+    The Summer component sums two or more inputs. These can be pilot control
+    inputs or state variables, and a bias can also be added in using the BIAS
+    keyword.  The form of the summer component specification is:
+<pre>
+    \<COMPONENT NAME="name" TYPE="SUMMER">
+      INPUT \<property>
+      INPUT \<property>
+      [BIAS \<value>]
+      [?]
+      [CLIPTO \<min> \<max> 1]
+      [OUTPUT \<property>]
+    \</COMPONENT>
+</pre>
+    Note that in the case of an input property the property name may be
+    immediately preceded by a minus sign. Here's an example of a summer
+    component specification:
+<pre>
+    \<COMPONENT NAME="Roll A/P Error summer" TYPE="SUMMER">
+      INPUT  velocities/p-rad_sec
+      INPUT -fcs/roll-ap-wing-leveler
+      INPUT  fcs/roll-ap-error-integrator
+      CLIPTO -1 1
+    \</COMPONENT>
+</pre>
+    Note that there can be only one BIAS statement per component.
+
+    @author Jon S. Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGSummer  : public FGFCSComponent
+{
+public:
+  /** Constructor.
+      @param fcs a pointer to the parent FGFCS object.
+      @param AC_cfg a pointer to the configuration file object. */
+  FGSummer(FGFCS* fcs, Element* element);
+  /// Destructor
+  ~FGSummer();
+
+  /// The execution method for this FCS component.
+  bool Run(void);
+
+private:
+  double Bias;
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp b/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp
new file mode 100644 (file)
index 0000000..0ac7684
--- /dev/null
@@ -0,0 +1,280 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGSwitch.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
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+The SWITCH component is defined as follows (see the API documentation for more
+information):
+
+<COMPONENT NAME="switch1" TYPE="SWITCH">
+  <TEST LOGIC="{AND|OR|DEFAULT}" OUTPUT="{property|value}">
+    {property} {conditional} {property|value}
+    <CONDITION_GROUP LOGIC="{AND|OR}">
+      {property} {conditional} {property|value}
+      ...
+    </CONDITION_GROUP>
+    ...
+  </TEST>
+  <TEST LOGIC="{AND|OR}" OUTPUT="{property|value}">
+    {property} {conditional} {property|value}
+    ...
+  </TEST>
+  ...
+</COMPONENT>
+
+Also, see the header file (FGSwitch.h) for further details.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGSwitch.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_SWITCH;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  string value, logic;
+  struct test *current_test;
+  Element *test_element, *condition_element;
+
+  test_element = element->GetElement();
+  while (test_element) {
+    if (test_element->GetName() == "default") {
+      tests.push_back(test());
+      current_test = &tests.back();
+      current_test->Logic = eDefault;
+    } else if (test_element->GetName() == "test") { // here's a test
+      tests.push_back(test());
+      current_test = &tests.back();
+      logic = test_element->GetAttributeValue("logic");
+      if (logic == "OR") current_test->Logic = eOR;
+      else if (logic == "AND") current_test->Logic = eAND;
+      else if (logic.size() == 0) current_test->Logic == eAND; // default
+      else { // error
+        cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl;
+      }
+      for (int i=0; i<test_element->GetNumDataLines(); i++)
+        current_test->conditions.push_back(FGCondition(test_element->GetDataLine(i), PropertyManager));
+
+      condition_element = test_element->GetElement(); // retrieve condition groups
+      while (condition_element) {
+        current_test->conditions.push_back(FGCondition(condition_element, PropertyManager));
+        condition_element = test_element->GetNextElement();
+      }
+
+    }
+
+    if (test_element->GetName() != "output") { // this is not an output element
+      value = test_element->GetAttributeValue("value");
+      if (value.empty()) {
+        cerr << "No VALUE supplied for switch component: " << Name << endl;
+      } else {
+        if (value.find_first_not_of("-.0123456789eE") == string::npos) {
+          // if true (and execution falls into this block), "value" is a number.
+          current_test->OutputVal = atof(value.c_str());
+        } else {
+          // "value" must be a property if execution passes to here.
+          if (value[0] == '-') {
+            current_test->sign = -1.0;
+            value.erase(0,1);
+          } else {
+            current_test->sign = 1.0;
+          }
+          current_test->OutputProp = PropertyManager->GetNode(value);
+        }
+      }
+    }
+
+    test_element = element->GetNextElement();
+  }
+
+  FGFCSComponent::bind();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGSwitch::~FGSwitch()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGSwitch::Run(void )
+{
+  vector <test>::iterator iTests = tests.begin();
+  vector <FGCondition>::iterator iConditions;
+  bool pass = false;
+
+  while (iTests < tests.end()) {
+    iConditions = iTests->conditions.begin();
+
+    if (iTests->Logic == eDefault) {
+      Output = iTests->GetValue();
+    } else if (iTests->Logic == eAND) {
+      pass = true;
+      while (iConditions < iTests->conditions.end()) {
+        if (!iConditions->Evaluate()) pass = false;
+        *iConditions++;
+      }
+    } else if (iTests->Logic == eOR) {
+      pass = false;
+      while (iConditions < iTests->conditions.end()) {
+        if (iConditions->Evaluate()) pass = true;
+        *iConditions++;
+      }
+    } else {
+      cerr << "Invalid logic test" << endl;
+    }
+
+    if (pass) {
+      Output = iTests->GetValue();
+      break;
+    }
+    *iTests++;
+  }
+
+  Clip();
+  if (IsOutput) SetOutput();
+
+  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 FGSwitch::Debug(int from)
+{
+  vector <test>::iterator iTests = tests.begin();
+  vector <FGCondition>::iterator iConditions;
+  string comp, scratch;
+  string indent = "        ";
+  bool first = false;
+
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      while (iTests < tests.end()) {
+
+        scratch = " if ";
+
+        switch(iTests->Logic) {
+        case (elUndef):
+          comp = " UNSET ";
+          cerr << "Unset logic for test condition" << endl;
+          break;
+        case (eAND):
+          comp = " AND ";
+          break;
+        case (eOR):
+          comp=" OR ";
+          break;
+        case (eDefault):
+          scratch = " by default.";
+          break;
+        default:
+          comp = " UNKNOWN ";
+          cerr << "Unknown logic for test condition" << endl;
+        }
+
+        if (iTests->OutputProp != 0L)
+          if (iTests->sign < 0)
+            cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
+          else
+            cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
+        else
+          cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
+
+        iConditions = iTests->conditions.begin();
+        first = true;
+        while (iConditions < iTests->conditions.end()) {
+          if (!first) cout << indent << comp << " ";
+          else cout << indent << " ";
+          first = false;
+          iConditions->PrintCondition();
+          cout << endl;
+          *iConditions++;
+        }
+        cout << endl;
+        *iTests++;
+      }
+      if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGSwitch" << endl;
+    if (from == 1) cout << "Destroyed:    FGSwitch" << 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;
+    }
+  }
+}
+
+} //namespace JSBSim
+
diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.h b/src/FDM/JSBSim/models/flight_control/FGSwitch.h
new file mode 100644 (file)
index 0000000..a6ef0db
--- /dev/null
@@ -0,0 +1,169 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGSwitch.h
+ Author:       Jon S. Berndt
+ Date started: 12/23/2002
+
+ ------------- Copyright (C)  -------------
+
+ 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
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGSWITCH_H
+#define FGSWITCH_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGFCSComponent.h"
+#include <input_output/FGXMLElement.h>
+#include "FGCondition.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_SWITCH "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates a switch for the flight control system.
+
+The SWITCH component models a switch - either on/off or a multi-choice rotary
+switch. The switch can represent a physical cockpit switch, or can represent a
+logical switch, where several conditions might need to be satisfied before a
+particular state is reached. The VALUE of the switch - the output value for the
+component - is chosen depending on the state of the switch. Each switch is
+comprised of two or more TESTs. Each TEST has a VALUE associated with it. The
+first TEST that evaluates to TRUE will set the output value of the switch
+according to the VALUE parameter belonging to that TEST. Each TEST contains one
+or more CONDITIONS, which each must be logically related (if there are more than
+one) given the value of the LOGIC parameter, and which takes the form:
+
+  property conditional property|value
+
+e.g.
+
+  qbar GE 21.0
+
+or,
+
+  roll_rate < pitch_rate
+
+Within a TEST, a CONDITION_GROUP can be specified. A CONDITION_GROUP allows for
+complex groupings of logical comparisons. Each CONDITION_GROUP contains
+additional conditions, as well as possibly additional CONDITION_GROUPs.
+
+<pre>
+\<COMPONENT NAME="switch1" TYPE="SWITCH"\>
+  \<TEST LOGIC="{AND|OR|DEFAULT}" VALUE="{property|value}"\>
+    {property} {conditional} {property|value}
+    \<CONDITION_GROUP LOGIC="{AND|OR}"\>
+      {property} {conditional} {property|value}
+      ...
+    \</CONDITION_GROUP\>
+    ...
+  \</TEST>
+  \<TEST LOGIC="{AND|OR}" VALUE="{property|value}"\>
+    {property} {conditional} {property|value}
+    ...
+  \</TEST\>
+  ...
+  [OUTPUT \<property>]
+\</COMPONENT\>
+</pre>
+
+Here's an example:
+<pre>
+\<COMPONENT NAME="Roll A/P Autoswitch" TYPE="SWITCH">
+  \<TEST LOGIC="DEFAULT" VALUE="0.0">
+  \</TEST>
+  \<TEST LOGIC="AND" VALUE="fcs/roll-ap-error-summer">
+    ap/attitude_hold == 1
+  \</TEST>
+\</COMPONENT>
+</pre>
+The above example specifies that the default value of the component (i.e. the
+output property of the component, addressed by the property, ap/roll-ap-autoswitch)
+is 0.0.  If or when the attitude hold switch is selected (property
+ap/attitude_hold takes the value 1), the value of the switch component will be
+whatever value fcs/roll-ap-error-summer is.
+@author Jon S. Berndt
+@version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGSwitch  : public FGFCSComponent
+{
+public:
+  FGSwitch(FGFCS* fcs, Element* element);
+  ~FGSwitch();
+
+  bool Run(void);
+
+  enum eLogic {elUndef=0, eAND, eOR, eDefault};
+  enum eComparison {ecUndef=0, eEQ, eNE, eGT, eGE, eLT, eLE};
+
+private:
+  FGFCS* fcs;
+
+  struct test {
+    vector <FGCondition> conditions;
+    eLogic Logic;
+    double OutputVal;
+    FGPropertyManager *OutputProp;
+    float sign;
+
+    double GetValue(void) {
+      if (OutputProp == 0L) return OutputVal;
+      else                  return OutputProp->getDoubleValue()*sign;
+    }
+
+    test(void) { // constructor for the test structure
+      Logic      = elUndef;
+      OutputVal  = 0.0;
+      OutputProp = 0L;
+      sign       = 1.0;
+    }
+
+  };
+
+  vector <test> tests;
+
+  void Debug(int from);
+};
+}
+#endif
diff --git a/src/FDM/JSBSim/models/flight_control/Makefile.am b/src/FDM/JSBSim/models/flight_control/Makefile.am
new file mode 100644 (file)
index 0000000..4ae764d
--- /dev/null
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libFlightControl.a 
+
+libFlightControl_a_SOURCES = FGCondition.cpp FGDeadBand.cpp FGFCSComponent.cpp \
+                            FGFilter.cpp FGGain.cpp FGGradient.cpp FGKinemat.cpp \
+                            FGSummer.cpp FGSwitch.cpp FGFCSFunction.cpp FGSensor.cpp
+
+noinst_HEADERS = FGCondition.h FGDeadBand.h FGFCSComponent.h FGFilter.h \
+                 FGGain.h FGGradient.h FGKinemat.h FGSummer.h FGSwitch.h FGFCSFunction.h \
+                 FGSensor.h
+
+INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp
new file mode 100644 (file)
index 0000000..3740ed9
--- /dev/null
@@ -0,0 +1,163 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+01/06/2005  DPC  Converted to new XML format
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGElectric.h"
+#include <models/FGPropulsion.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_ELECTRIC;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGElectric::FGElectric(FGFDMExec* exec, Element *el, int engine_number)
+  : FGEngine(exec, el, engine_number)
+{
+  string token;
+
+  Type = etElectric;
+  PowerWatts = 745.7;
+  hptowatts = 745.7;
+
+  dt = State->Getdt();
+
+  if (el->FindElement("power"))
+    PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS");
+
+  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(string delimeter)
+{
+  return ""; // currently no labels are returned for this engine
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGElectric::GetEngineValues(string delimeter)
+{
+  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/models/propulsion/FGElectric.h b/src/FDM/JSBSim/models/propulsion/FGElectric.h
new file mode 100644 (file)
index 0000000..84aa378
--- /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 <input_output/FGXMLElement.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, Element *el, int engine_number);
+  /// Destructor
+  ~FGElectric();
+
+  double Calculate(void);
+  double GetPowerAvailable(void) {return PowerAvailable;}
+  double CalcFuelNeed(void);
+  double getRPM(void) {return RPM;}
+  string GetEngineLabels(string delimeter);
+  string GetEngineValues(string delimeter);
+
+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
diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp
new file mode 100644 (file)
index 0000000..a385088
--- /dev/null
@@ -0,0 +1,358 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <fstream>
+#  else
+#    include <fstream.h>
+#  endif
+#else
+#  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
+#    include <fstream.h>
+#  else
+#    include <fstream>
+#  endif
+#endif
+
+#include "FGEngine.h"
+#include "FGTank.h"
+#include "FGPropeller.h"
+#include "FGNozzle.h"
+#include <input_output/FGXMLParse.h>
+#include <math/FGColumnVector3.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_ENGINE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
+                      : EngineNumber(engine_number)
+{
+  Element* local_element;
+  FGColumnVector3 location, orientation;
+
+  Name = "";
+  Type = etUnknown;
+  X = Y = Z = 0.0;
+  EnginePitch = EngineYaw = 0.0;
+  SLFuelFlowMax = SLOxiFlowMax = 0.0;
+  MaxThrottle = 1.0;
+  MinThrottle = 0.0;
+  Thrust = 0.0;
+  Throttle = 0.0;
+  Mixture = 1.0;
+  Starter = false;
+  FuelNeed = OxidizerNeed = 0.0;
+  Starved = Running = Cranking = false;
+  PctPower = 0.0;
+  TrimMode = false;
+  FuelFlow_gph = 0.0;
+  FuelFlow_pph = 0.0;
+  FuelFreeze = false;
+
+  FDMExec = exec;
+  State = FDMExec->GetState();
+  Atmosphere = FDMExec->GetAtmosphere();
+  FCS = FDMExec->GetFCS();
+  Propulsion = FDMExec->GetPropulsion();
+  Aircraft = FDMExec->GetAircraft();
+  Propagate = FDMExec->GetPropagate();
+  Auxiliary = FDMExec->GetAuxiliary();
+
+  PropertyManager = FDMExec->GetPropertyManager();
+
+  Name = engine_element->GetAttributeValue("name");
+
+// Find and set engine location
+
+  local_element = engine_element->GetParent()->FindElement("location");
+  if (local_element)  location = local_element->FindElementTripletConvertTo("IN");
+  else      cerr << "No engine location found for this engine." << endl;
+
+  local_element = engine_element->GetParent()->FindElement("orient");
+  if (local_element)  orientation = local_element->FindElementTripletConvertTo("IN");
+  else          cerr << "No engine orientation found for this engine." << endl;
+
+  SetPlacement(location, orientation);
+
+  // Load thruster
+  local_element = engine_element->GetParent()->FindElement("thruster");
+  if (local_element) {
+    LoadThruster(local_element);
+  } else {
+    cerr << "No thruster definition supplied with engine definition." << endl;
+  }
+
+  // Load feed tank[s] references
+  local_element = engine_element->GetParent()->FindElement("feed");
+  if (local_element) {
+    while (local_element) {
+      AddFeedTank((int)local_element->GetDataAsNumber());
+      local_element = engine_element->GetParent()->FindNextElement("feed");
+    }
+  } else {
+    cerr << "No feed tank specified in engine definition." << endl;
+  }
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGEngine::~FGEngine()
+{
+  if (Thruster) delete Thruster;
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// This base class function should be called from within the
+// derived class' Calculate() function before any other calculations are done.
+// This base class method removes fuel from the fuel tanks as appropriate,
+// and sets the starved flag if necessary.
+
+void FGEngine::ConsumeFuel(void)
+{
+  if (FuelFreeze) return;
+  if (TrimMode) return;
+
+  unsigned int i;
+  double Fshortage, Oshortage, TanksWithFuel, TanksWithOxidizer;
+  FGTank* Tank;
+  bool haveOxTanks = false;
+  Fshortage = Oshortage = TanksWithFuel = TanksWithOxidizer = 0.0;
+
+  // count how many assigned tanks have fuel
+  for (i=0; i<SourceTanks.size(); i++) {
+    Tank = Propulsion->GetTank(SourceTanks[i]);
+    if (Tank->GetType() == FGTank::ttFUEL){
+      if (Tank->GetContents() > 0.0) ++TanksWithFuel;
+    } else if (Tank->GetType() == FGTank::ttOXIDIZER) {
+      haveOxTanks = true;
+      if (Tank->GetContents() > 0.0) ++TanksWithOxidizer;
+    }
+  }
+  if (TanksWithFuel==0 || (haveOxTanks && TanksWithOxidizer==0)) return;
+
+  for (i=0; i<SourceTanks.size(); i++) {
+    Tank = Propulsion->GetTank(SourceTanks[i]);
+    if (Tank->GetType() == FGTank::ttFUEL) {
+       Fshortage += Tank->Drain(CalcFuelNeed()/TanksWithFuel);
+    } else if (Tank->GetType() == FGTank::ttOXIDIZER) {
+       Oshortage += Tank->Drain(CalcOxidizerNeed()/TanksWithOxidizer);
+    }
+  }
+
+  if (Fshortage < 0.00 || Oshortage < 0.00) Starved = true;
+  else Starved = false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGEngine::CalcFuelNeed(void)
+{
+  FuelNeed = SLFuelFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
+  return FuelNeed;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGEngine::CalcOxidizerNeed(void)
+{
+  OxidizerNeed = SLOxiFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
+  return OxidizerNeed;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGEngine::SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation)
+{
+  X = location(eX);
+  Y = location(eY);
+  Z = location(eZ);
+  EnginePitch = orientation(ePitch);
+  EngineYaw = orientation (eYaw);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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(Element *thruster_element)
+{
+  string token, fullpath, localpath;
+  string thruster_filename, thruster_fullpathname, thrType;
+  double xLoc, yLoc, zLoc, Pitch, Yaw;
+  double P_Factor = 0, Sense = 0.0;
+  string enginePath = FDMExec->GetEnginePath();
+  string aircraftPath = FDMExec->GetAircraftPath();
+  FGXMLParse thruster_file_parser;
+  Element *document, *element;
+  ifstream thruster_file;
+  FGColumnVector3 location, orientation;
+
+# ifndef macintosh
+  string separator = "/";
+# else
+  string separator = ";";
+# endif
+
+  fullpath = enginePath + separator;
+  localpath = aircraftPath + separator + "Engines" + separator;
+
+  thruster_filename = thruster_element->GetAttributeValue("file");
+  if ( !thruster_filename.empty()) {
+    thruster_fullpathname = fullpath + thruster_filename + ".xml";
+    thruster_file.open(thruster_fullpathname.c_str());
+    if ( !thruster_file.is_open()) {
+      thruster_fullpathname = localpath + thruster_filename + ".xml";
+      thruster_file.open(thruster_fullpathname.c_str());
+      if ( !thruster_file.is_open()) {
+        cerr << "Could not open thruster file: " << thruster_filename << ".xml" << endl;
+        return false;
+      } else {
+        thruster_file.close();
+      }
+    } else {
+      thruster_file.close();
+    }
+  } else {
+    cerr << "No thruster filename given." << endl;
+    return false;
+  }
+
+  readXML(thruster_fullpathname, thruster_file_parser);
+  document = thruster_file_parser.GetDocument(); // document holds the thruster description
+  document->SetParent(thruster_element);
+
+  thrType = document->GetName();
+
+  if (thrType == "propeller") {
+    Thruster = new FGPropeller(FDMExec, document, EngineNumber);
+  } else if (thrType == "nozzle") {
+    Thruster = new FGNozzle(FDMExec, document, EngineNumber);
+  } else if (thrType == "direct") {
+    Thruster = new FGThruster( FDMExec, document, EngineNumber);
+  }
+
+  Thruster->SetdeltaT(State->Getdt() * Propulsion->GetRate());
+
+  Debug(2);
+  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 FGEngine::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+
+    }
+    if (from == 2) { // After thruster loading
+      cout << "      X = " << Thruster->GetLocationX() << endl;
+      cout << "      Y = " << Thruster->GetLocationY() << endl;
+      cout << "      Z = " << Thruster->GetLocationZ() << endl;
+      cout << "      Pitch = " << Thruster->GetAnglesToBody(ePitch) << endl;
+      cout << "      Yaw = " << Thruster->GetAnglesToBody(eYaw) << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGEngine" << endl;
+    if (from == 1) cout << "Destroyed:    FGEngine" << 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/models/propulsion/FGEngine.h b/src/FDM/JSBSim/models/propulsion/FGEngine.h
new file mode 100644 (file)
index 0000000..a6e820a
--- /dev/null
@@ -0,0 +1,236 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGEngine.h
+ Author:       Jon S. Berndt
+ Date started: 01/21/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.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+Based on Flightgear code, which is based on LaRCSim. This class simulates
+a generic engine.
+
+HISTORY
+--------------------------------------------------------------------------------
+01/21/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGENGINE_H
+#define FGENGINE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_STRING
+   SG_USING_STD(string);
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <vector>
+#  else
+#    include <vector.h>
+#  endif
+#else
+#  include <vector>
+#  include <string>
+#endif
+
+#include <FGJSBBase.h>
+#include "FGThruster.h"
+#include <input_output/FGPropertyManager.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_ENGINE "$Id$"
+
+using std::string;
+using std::vector;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFDMExec;
+class FGState;
+class FGAtmosphere;
+class FGFCS;
+class FGAircraft;
+class FGPropagate;
+class FGPropulsion;
+class FGAuxiliary;
+class FGThruster;
+class Element;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Base class for all engines.
+    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$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGEngine : public FGJSBBase
+{
+public:
+  FGEngine(FGFDMExec* exec, Element* el, int engine_number);
+  virtual ~FGEngine();
+
+  enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etTurboprop, etElectric};
+
+  EngineType      GetType(void) { return Type; }
+  virtual string  GetName(void) { return Name; }
+
+  // Engine controls
+  virtual double  GetThrottleMin(void) { return MinThrottle; }
+  virtual double  GetThrottleMax(void) { return MaxThrottle; }
+  virtual double  GetThrottle(void) { return Throttle; }
+  virtual double  GetMixture(void) { return Mixture; }
+  virtual bool    GetStarter(void) { return Starter; }
+
+  virtual double getFuelFlow_gph () const {return FuelFlow_gph;}
+  virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
+  virtual double GetThrust(void) { return Thrust; }
+  virtual bool   GetStarved(void) { return Starved; }
+  virtual bool   GetRunning(void) { return Running; }
+  virtual bool   GetCranking(void) { return Cranking; }
+
+  virtual void SetStarved(bool tt) { Starved = tt; }
+  virtual void SetStarved(void)    { Starved = true; }
+
+  virtual void SetRunning(bool bb) { Running=bb; }
+  virtual void SetName(string name) { Name = name; }
+  virtual void AddFeedTank(int tkID);
+  virtual void SetFuelFreeze(bool f) { FuelFreeze = f; }
+
+  virtual void SetStarter(bool s) { Starter = s; }
+
+  /** Calculates the thrust of the engine, and other engine functions.
+      @return Thrust in pounds */
+  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
+      derived class' Calculate() function before any other calculations are
+      done. This base class method removes fuel from the fuel tanks as
+      appropriate, and sets the starved flag if necessary. */
+  virtual void ConsumeFuel(void);
+
+  /** The fuel need is calculated based on power levels and flow rate for that
+      power level. It is also turned from a rate into an actual amount (pounds)
+      by multiplying it by the delta T and the rate.
+      @return Total fuel requirement for this engine in pounds. */
+  virtual double CalcFuelNeed(void);
+
+  /** The oxidizer need is calculated based on power levels and flow rate for that
+      power level. It is also turned from a rate into an actual amount (pounds)
+      by multiplying it by the delta T and the rate.
+      @return Total oxidizer requirement for this engine in pounds. */
+  virtual double CalcOxidizerNeed(void);
+
+  /// Sets engine placement information
+  virtual void SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation);
+
+  virtual double GetPowerAvailable(void) {return 0.0;};
+
+  virtual bool GetTrimMode(void) {return TrimMode;}
+  virtual void SetTrimMode(bool state) {TrimMode = state;}
+
+  virtual FGColumnVector3& GetBodyForces(void);
+  virtual FGColumnVector3& GetMoments(void);
+
+  bool LoadThruster(Element *el);
+  FGThruster* GetThruster(void) {return Thruster;}
+
+  virtual string GetEngineLabels(string delimeter) = 0;
+  virtual string GetEngineValues(string delimeter) = 0;
+
+protected:
+  FGPropertyManager* PropertyManager;
+  string Name;
+  const int   EngineNumber;
+  EngineType Type;
+  double X, Y, Z;
+  double EnginePitch;
+  double EngineYaw;
+  double SLFuelFlowMax;
+  double SLOxiFlowMax;
+  double MaxThrottle;
+  double MinThrottle;
+
+  double Thrust;
+  double Throttle;
+  double Mixture;
+  double FuelNeed;
+  double OxidizerNeed;
+  double PctPower;
+  bool  Starter;
+  bool  Starved;
+  bool  Running;
+  bool  Cranking;
+  bool  TrimMode;
+  bool  FuelFreeze;
+
+  double FuelFlow_gph;
+  double FuelFlow_pph;
+
+  FGFDMExec*      FDMExec;
+  FGState*        State;
+  FGAtmosphere*   Atmosphere;
+  FGFCS*          FCS;
+  FGPropulsion*   Propulsion;
+  FGAircraft*     Aircraft;
+  FGPropagate*    Propagate;
+  FGAuxiliary*    Auxiliary;
+  FGThruster*     Thruster;
+
+  vector <int> SourceTanks;
+  void Debug(int from);
+};
+}
+#include <FGState.h>
+#include <FGFDMExec.h>
+#include <models/FGAtmosphere.h>
+#include <models/FGFCS.h>
+#include <models/FGAircraft.h>
+#include <models/FGPropagate.h>
+#include <models/FGPropulsion.h>
+#include <models/FGAuxiliary.h>
+#include <models/propulsion/FGThruster.h>
+#include <input_output/FGXMLElement.h>
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGForce.cpp b/src/FDM/JSBSim/models/propulsion/FGForce.cpp
new file mode 100644 (file)
index 0000000..f54ac99
--- /dev/null
@@ -0,0 +1,183 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Source:       FGForce.cpp
+ Author:       Tony Peden
+ Date started: 6/10/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
+--------------------------------------------------------------------------------
+6/10/00  TP   Created
+
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+The purpose of this class is to provide storage for computed forces and
+encapsulate all the functionality associated with transforming those
+forces from their native coord system to the body system.  This includes
+computing the moments due to the difference between the point of application
+and the cg.
+
+*/
+
+#include <FGFDMExec.h>
+#include <models/FGAircraft.h>
+#include <models/FGPropagate.h>
+#include <models/FGMassBalance.h>
+#include <FGState.h>
+#include "FGForce.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FORCE;
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGForce::FGForce(FGFDMExec *FDMExec) :
+                 ttype(tNone),
+                 fdmex(FDMExec)
+{
+  mT(1,1) = 1; //identity matrix
+  mT(2,2) = 1;
+  mT(3,3) = 1;
+  vSense.InitMatrix(1);
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGForce::~FGForce()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGForce::GetBodyForces(void)
+{
+  vFb = Transform()*(vFn.multElementWise(vSense));
+
+  // Find the distance from this vector's acting location to the cg; this
+  // needs to be done like this to convert from structural to body coords.
+  // CG and RP values are in inches
+
+  vDXYZ = fdmex->GetMassBalance()->StructuralToBody(vActingXYZn);
+
+  vM = vMn + vDXYZ*vFb;
+
+  return vFb;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGMatrix33 FGForce::Transform(void)
+{
+  switch(ttype) {
+  case tWindBody:
+    return fdmex->GetState()->GetTs2b();
+  case tLocalBody:
+    return fdmex->GetPropagate()->GetTl2b();
+  case tCustom:
+  case tNone:
+    return mT;
+  default:
+    cout << "Unrecognized tranform requested from FGForce::Transform()" << endl;
+    exit(1);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGForce::SetAnglesToBody(double broll, double bpitch, double byaw)
+{
+  if (ttype == tCustom) {
+    double cp,sp,cr,sr,cy,sy;
+    vOrient(ePitch) = bpitch;
+    vOrient(eRoll) = broll;
+    vOrient(eYaw) = byaw;
+
+    cp=cos(bpitch); sp=sin(bpitch);
+    cr=cos(broll);  sr=sin(broll);
+    cy=cos(byaw);   sy=sin(byaw);
+
+    mT(1,1)=cp*cy;
+    mT(1,2)=cp*sy;
+    mT(1,3)=-1*sp;
+
+    mT(2,1)=sr*sp*cy-cr*sy;
+    mT(2,2)=sr*sp*sy+cr*cy;
+    mT(2,3)=sr*cp;
+
+    mT(3,1)=cr*sp*cy+sr*sy;
+    mT(3,2)=cr*sp*sy-sr*cy;
+    mT(3,3)=cr*cp;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGForce::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: FGForce" << endl;
+    if (from == 1) cout << "Destroyed:    FGForce" << 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/models/propulsion/FGForce.h b/src/FDM/JSBSim/models/propulsion/FGForce.h
new file mode 100644 (file)
index 0000000..0f69897
--- /dev/null
@@ -0,0 +1,341 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGForce.h
+ Author:       Tony Peden
+ Date started: 5/20/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
+--------------------------------------------------------------------------------
+5/20/00  TP   Created
+
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+The purpose of this class is to provide storage for computed forces and
+encapsulate all the functionality associated with transforming those
+forces from their native coord system to the body system.  This includes
+computing the moments due to the difference between the point of application
+and the cg.
+
+CAVEAT:  if the custom transform is used for wind-to-body transforms then the
+         user *must* always pass this class the negative of beta. This is true
+         because sideslip angle does not follow the right hand rule i.e. it is
+         positive for aircraft nose left sideslip.  Note that use of the custom
+         transform for this purpose shouldn't be necessary as it is already
+         provided by SetTransform(tWindBody) and is not subject to the same
+         restriction.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGFORCE_H
+#define FGFORCE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <FGFDMExec.h>
+#include <FGJSBBase.h>
+#include <math/FGMatrix33.h>
+#include <math/FGColumnVector3.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FORCE "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Utility class that aids in the conversion of forces between coordinate systems
+    and calculation of moments.
+<br><h3>Resolution of Applied Forces into Moments and Body Axes Components</h3>
+<br><p>
+All forces acting on the aircraft that cannot be considered a change in weight
+need to be resolved into body axis components so that the aircraft acceleration
+vectors, both translational and rotational, can be computed. Furthermore, the
+moments produced by each force that does not act at a location corresponding to
+the center of gravity also need to be computed. Unfortunately, the math required
+to do this can be a bit messy and errors are easily introduced so the class
+FGForce was created to provide these services in a consistent and reusable
+manner.<br><br></p>
+
+<h4>Basic usage</h4>
+
+<p>FGForce requires that its users supply it with the location of the applied
+force vector in JSBSim structural coordinates, the sense of each axis in that
+coordinate system relative to the body system, the orientation of the vector
+also relative to body coordinates and, of course, the force vector itself. With
+this information it will compute both the body axis force components and the
+resulting moments. Any moments inherently produced by the native system can be
+supplied as well and they will be summed with those computed.</p>
+
+<p>A good example for demonstrating the use of this class are the aerodynamic
+forces: lift, drag, and side force and the aerodynamic moments about the pitch,
+roll and yaw axes. These "native" forces and moments are computed and stored
+in the FGColumnVector objects vFs and vMoments. Their native coordinate system
+is often referred to as the wind system and is defined as a right-handed system
+having its x-axis aligned with the relative velocity vector and pointing towards
+the rear of the aircraft , the y-axis extending out the right wing, and the
+z-axis directed upwards. This is different than body axes; they are defined such
+that the x-axis is lies on the aircraft's roll axis and positive forward, the
+y-axis is positive out the right wing, and the z-axis is positive downwards. In
+this instance, JSBSim already provides the needed transform and FGForce can make
+use of it by calling SetTransformType() once an object is created:</p>
+
+<p><tt>FGForce fgf(FDMExec);</tt><br>
+<tt>fgf.SetTransformType(tWindBody);</tt><br><br>
+
+This call need only be made once for each object. The available transforms are
+defined in the enumerated type TransformType and are tWindBody, tLocalBody,
+tCustom, and tNone. The local-to-body transform, like the wind-to-body, also
+makes use of that already available in JSBSim. tNone sets FGForce to do no
+angular transform at all, and tCustom allows for modeling force vectors at
+arbitrary angles relative to the body system such as that produced by propulsion
+systems. Setting up and using a custom transform is covered in more detail below.
+Continuing with the example, the point of application of the aerodynamic forces,
+the aerodynamic reference point in JSBSim, also needs to be set:</p>
+<p><tt>
+fgf.SetLocation(x, y, z)</tt></p>
+
+<p>where x, y, and z are in JSBSim structural coordinates.</p>
+
+<p>Initialization is complete and the FGForce object is ready to do its job. As
+stated above, the lift, drag, and side force are computed and stored in the
+vector vFs and need to be passed to FGForce:</p>
+
+<p><tt>fgf.SetNativeForces(vFs);</tt> </p>
+
+<p>The same applies to the aerodynamic pitching, rolling and yawing moments:</p>
+
+<p><tt>fgf.SetNativeMoments(vMoments);</tt></p>
+
+<p>Note that storing the native forces and moments outside of this class is not
+strictly necessary, overloaded SetNativeForces() and SetNativeMoments() methods
+which each accept three doubles (rather than a vector) are provided and can be
+repeatedly called without incurring undue overhead. The body axes force vector
+can now be retrieved by calling:</p>
+
+<p><tt>vFb=fgf.GetBodyForces();</tt></p>
+
+<p>This method is where the bulk of the work gets done so calling it more than
+once for the same set of native forces and moments should probably be avoided.
+Note that the moment calculations are done here as well so they should not be
+retrieved after calling the GetBodyForces() method:</p>
+
+<p><tt>vM=fgf.GetMoments();</tt> </p>
+
+<p>As an aside, the native moments are not needed to perform the computations
+correctly so, if the FGForce object is not being used to store them then an
+alternate approach is to avoid the SetNativeMoments call and perform the sum</p>
+
+<p><tt>vMoments+=fgf.GetMoments();</tt> <br><br>
+
+after the forces have been retrieved. </p>
+
+<h4>Use of the Custom Transform Type</h4>
+
+<p>In cases where the native force vector is not aligned with the body, wind, or
+local coordinate systems a custom transform type is provided. A vectorable engine
+nozzle will be used to demonstrate its usage. Initialization is much the same:</p>
+
+<p><tt>FGForce fgf(FDMExec);</tt> <br>
+<tt>fgf.SetTransformType(tCustom);</tt> <br>
+<tt>fgf.SetLocation(x,y,z);</tt> </p>
+
+<p>Except that here the tCustom transform type is specified and the location of
+the thrust vector is used rather than the aerodynamic reference point. Thrust is
+typically considered to be positive when directed aft while the body x-axis is
+positive forward and, if the native system is right handed, the z-axis will be
+reversed as well. These differences in sense need to be specified using by the
+call: </p>
+
+<p><tt>fgf.SetSense(-1,1,-1);</tt></p>
+
+<p>The angles are specified by calling the method: </p>
+
+<p><tt>fgf.SetAnglesToBody(pitch, roll, yaw);</tt> </p>
+
+<p>in which the transform matrix is computed. Note that these angles should be
+taken relative to the body system and not the local as the names might suggest.
+For an aircraft with vectorable thrust, this method will need to be called
+every time the nozzle angle changes, a fixed engine/nozzle installation, on the
+other hand, will require it to be be called only once.</p>
+
+<p>Retrieval of the computed forces and moments is done as detailed above.</p>
+<br>
+<blockquote>
+    <p><i>CAVEAT: If the custom system is used to compute
+    the wind-to-body transform, then the sign of the sideslip
+    angle must be reversed when calling SetAnglesToBody().
+    This is true because sideslip angle does not follow the right
+    hand rule. Using the custom transform type this way
+    should not be necessary, as it is already provided as a built
+    in type (and the sign differences are correctly accounted for).</i>
+    <br></p>
+</blockquote>
+
+<h4>Use as a Base Type</h4>
+
+<p>For use as a base type, the native force and moment vector data members are
+defined as protected. In this case the SetNativeForces() and SetNativeMoments()
+methods need not be used and, instead, the assignments to vFn, the force vector,
+and vMn, the moments, can be made directly. Otherwise, the usage is similar.<br>
+<br><br></p>
+
+    @author Tony Peden
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGForce : public FGJSBBase
+{
+public:
+  /// Constructor
+  FGForce(FGFDMExec *FDMExec);
+  /// Destructor
+  ~FGForce();
+
+  enum TransformType { tNone, tWindBody, tLocalBody, tCustom } ttype;
+
+  inline void SetNativeForces(double Fnx, double Fny, double Fnz) {
+    vFn(1)=Fnx;
+    vFn(2)=Fny;
+    vFn(3)=Fnz;
+  }
+  inline void SetNativeForces(FGColumnVector3 vv) { vFn = vv; };
+
+  inline void SetNativeMoments(double Ln,double Mn, double Nn) {
+    vMn(1)=Ln;
+    vMn(2)=Mn;
+    vMn(3)=Nn;
+  }
+  inline void SetNativeMoments(FGColumnVector3 vv) { vMn = vv; }
+
+  inline FGColumnVector3& GetNativeForces(void) { return vFn; }
+  inline FGColumnVector3& GetNativeMoments(void) { return vMn; }
+
+  FGColumnVector3& GetBodyForces(void);
+
+  inline FGColumnVector3& GetMoments(void) { return vM; }
+
+  // Normal point of application, JSBsim structural coords
+  // (inches, x +back, y +right, z +up)
+  inline void SetLocation(double x, double y, double z) {
+    vXYZn(eX) = x;
+    vXYZn(eY) = y;
+    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
+      not be the same as where the object resides. One area where this
+      is true is P-Factor modeling.
+      @param x acting location of force
+      @param y acting location of force
+      @param z acting location of force    */
+  inline void SetActingLocation(double x, double y, double z) {
+    vActingXYZn(eX) = x;
+    vActingXYZn(eY) = y;
+    vActingXYZn(eZ) = z;
+  }
+  inline void SetLocationX(double x) {vXYZn(eX) = x; vActingXYZn(eX) = x;}
+  inline void SetLocationY(double y) {vXYZn(eY) = y; vActingXYZn(eY) = y;}
+  inline void SetLocationZ(double z) {vXYZn(eZ) = z; vActingXYZn(eZ) = z;}
+  inline double SetActingLocationX(double x) {vActingXYZn(eX) = x; return x;}
+  inline double SetActingLocationY(double y) {vActingXYZn(eY) = y; return y;}
+  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);}
+  inline double GetActingLocationX( void ) { return vActingXYZn(eX);}
+  inline double GetActingLocationY( void ) { return vActingXYZn(eY);}
+  inline double GetActingLocationZ( void ) { return vActingXYZn(eZ);}
+  FGColumnVector3& GetLocation(void) { return vXYZn; }
+  FGColumnVector3& GetActingLocation(void) { return vActingXYZn; }
+
+  //these angles are relative to body axes, not earth!!!!!
+  //I'm using these because pitch, roll, and yaw are easy to visualize,
+  //there's no equivalent to roll in wind axes i.e. alpha, ? , beta
+  //making up new names or using these is a toss-up: either way people
+  //are going to get confused.
+  //They are in radians.
+
+  void SetAnglesToBody(double broll, double bpitch, double byaw);
+  inline void  SetAnglesToBody(FGColumnVector3 vv) {
+    SetAnglesToBody(vv(eRoll), vv(ePitch), vv(eYaw));
+  }
+
+  inline void SetSense(double x, double y, double z) { vSense(eX)=x, vSense(eY)=y, vSense(eZ)=z; }
+  inline void SetSense(FGColumnVector3 vv) { vSense=vv; }
+
+  inline FGColumnVector3& GetAnglesToBody(void) {return vOrient;}
+  inline double GetAnglesToBody(int axis) {return vOrient(axis);}
+  inline FGColumnVector3& GetSense(void) { return vSense; }
+
+  inline void SetTransformType(TransformType ii) { ttype=ii; }
+  inline TransformType GetTransformType(void) { return ttype; }
+
+  FGMatrix33 Transform(void);
+
+protected:
+  FGFDMExec *fdmex;
+  FGColumnVector3 vFn;
+  FGColumnVector3 vMn;
+  FGColumnVector3 vH;
+  FGColumnVector3 vOrient;
+
+private:
+  FGColumnVector3 vFb;
+  FGColumnVector3 vM;
+  FGColumnVector3 vXYZn;
+  FGColumnVector3 vActingXYZn;
+  FGColumnVector3 vDXYZ;
+  FGColumnVector3 vSense;
+
+  FGMatrix33 mT;
+
+  void Debug(int from);
+};
+}
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp b/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp
new file mode 100644 (file)
index 0000000..bb5d919
--- /dev/null
@@ -0,0 +1,196 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGNozzle.cpp
+ Author:       Jon S. Berndt
+ Date started: 08/24/00
+ Purpose:      Encapsulates the nozzle object
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/24/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <sstream>
+
+#include "FGNozzle.h"
+#include <models/FGAtmosphere.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_NOZZLE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGNozzle::FGNozzle(FGFDMExec* FDMExec, Element* nozzle_element, int num) : FGThruster(FDMExec)
+{
+
+  if (nozzle_element->FindElement("pe"))
+    PE = nozzle_element->FindElementValueAsNumberConvertTo("pe", "PSF");
+  else {
+    cerr << "Fatal Error: Nozzle exit pressure must be given in nozzle config file." << endl;
+    exit(-1);
+  }
+  if (nozzle_element->FindElement("expr"))
+    ExpR = nozzle_element->FindElementValueAsNumber("expr");
+  else {
+    cerr << "Fatal Error: Nozzle expansion ratio must be given in nozzle config file." << endl;
+    exit(-1);
+  }
+  if (nozzle_element->FindElement("nzl_eff"))
+    nzlEff = nozzle_element->FindElementValueAsNumber("nzl_eff");
+  else {
+    cerr << "Fatal Error: Nozzle efficiency must be given in nozzle config file." << endl;
+    exit(-1);
+  }
+  if (nozzle_element->FindElement("diam"))
+    Diameter = nozzle_element->FindElementValueAsNumberConvertTo("diam", "FT");
+  else {
+    cerr << "Fatal Error: Nozzle diameter must be given in nozzle config file." << endl;
+    exit(-1);
+  }
+
+  Thrust = 0;
+  ReverserAngle = 0.0;
+  Type = ttNozzle;
+  Area2 = (Diameter*Diameter/4.0)*M_PI;
+  AreaT = Area2/ExpR;
+
+//  char property_name[80];
+//  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
+//  PropertyManager->Tie( property_name, &ThrustCoeff );
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGNozzle::~FGNozzle()
+{
+//  char property_name[80];
+//  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
+//  PropertyManager->Untie( property_name );
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGNozzle::Calculate(double CfPc)
+{
+  double pAtm = fdmex->GetAtmosphere()->GetPressure();
+  Thrust = max((double)0.0, (CfPc * AreaT + (PE - pAtm)*Area2) * nzlEff);
+  vFn(1) = Thrust * cos(ReverserAngle);
+
+  ThrustCoeff = max((double)0.0, CfPc / ((pAtm - PE) * Area2));
+
+  return Thrust;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGNozzle::GetPowerRequired(void)
+{
+  return PE;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGNozzle::GetThrusterLabels(int id, string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_Thrust[" << id << ']';
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGNozzle::GetThrusterValues(int id, string delimeter)
+{
+  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
+//       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 FGNozzle::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "      Nozzle Name: " << Name << endl;
+      cout << "      Nozzle Exit Pressure = " << PE << endl;
+      cout << "      Nozzle Expansion Ratio = " << ExpR << endl;
+      cout << "      Nozzle Efficiency = " << nzlEff << endl;
+      cout << "      Nozzle Diameter = " << Diameter << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGNozzle" << endl;
+    if (from == 1) cout << "Destroyed:    FGNozzle" << 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/models/propulsion/FGNozzle.h b/src/FDM/JSBSim/models/propulsion/FGNozzle.h
new file mode 100644 (file)
index 0000000..4b7f308
--- /dev/null
@@ -0,0 +1,94 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGNozzle.h
+ Author:       Jon S. Berndt
+ Date started: 08/24/00
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/24/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGNOZZLE_H
+#define FGNOZZLE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGThruster.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_NOZZLE "$Id$";
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models a rocket nozzle.
+    @author Jon S. Berndt
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGNozzle : public FGThruster {
+
+public:
+  /// Constructor
+  FGNozzle(FGFDMExec* exec, Element* el, int num = 0);
+  /// Destructor
+  ~FGNozzle();
+
+  double Calculate(double CfPc);
+  double GetPowerRequired(void);
+  string GetThrusterLabels(int id, string delimeter);
+  string GetThrusterValues(int id, string delimeter);
+
+private:
+  double ReverserAngle;
+  double PE;
+  double ExpR;
+  double nzlEff;
+  double Diameter;
+  double AreaT;
+  double Area2;
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
new file mode 100644 (file)
index 0000000..e40a017
--- /dev/null
@@ -0,0 +1,827 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGPiston.cpp
+ Author:       Jon S. Berndt, JSBSim framework
+               Dave Luff, Piston engine model
+ Date started: 09/12/2000
+ Purpose:      This module models a Piston engine
+
+ ------------- Copyright (C) 2000  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 descends from the FGEngine class and models a Piston engine based on
+parameters given in the engine config file for this class
+
+HISTORY
+--------------------------------------------------------------------------------
+09/12/2000  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <sstream>
+
+#include "FGPiston.h"
+#include <models/FGPropulsion.h>
+#include "FGPropeller.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_PISTON;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
+  : FGEngine(exec, el, engine_number),
+  R_air(287.3),                  // Gas constant for air J/Kg/K
+  rho_fuel(800),                 // estimate
+  calorific_value_fuel(47.3e6),
+  Cp_air(1005),                  // Specific heat (constant pressure) J/Kg/K
+  Cp_fuel(1700)
+{
+  string token;
+
+  // Defaults and initializations
+
+  Type = etPiston;
+
+  // These items are read from the configuration file
+
+  Cycles = 2;
+  IdleRPM = 600;
+  Displacement = 360;
+  MaxHP = 200;
+  MinManifoldPressure_inHg = 6.5;
+  MaxManifoldPressure_inHg = 28.5;
+
+  // These are internal program variables
+
+  crank_counter = 0;
+  OilTemp_degK = 298;
+  ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg
+  minMAP = 21950;
+  maxMAP = 96250;
+  MAP = Atmosphere->GetPressure() * psftopa;
+  CylinderHeadTemp_degK = 0.0;
+  Magnetos = 0;
+  ExhaustGasTemp_degK = 0.0;
+  EGT_degC = 0.0;
+
+  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;
+  }
+  for (i=0; i<FG_MAX_BOOST_SPEEDS-1; i++) {
+    BoostSwitchAltitude[i] = 0.0;
+    BoostSwitchPressure[i] = 0.0;
+  }
+  // Initialisation
+  volumetric_efficiency = 0.8;  // Actually f(speed, load) but this will get us running
+
+  // 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;
+
+  Power_Mixture_Correlation = new FGTable(13);
+  *Power_Mixture_Correlation << (14.7/1.6) << 78.0;
+  *Power_Mixture_Correlation << 10 <<  86.0;
+  *Power_Mixture_Correlation << 11 <<  93.5;
+  *Power_Mixture_Correlation << 12 <<  98.0;
+  *Power_Mixture_Correlation << 13 << 100.0;
+  *Power_Mixture_Correlation << 14 <<  99.0;
+  *Power_Mixture_Correlation << 15 <<  96.4;
+  *Power_Mixture_Correlation << 16 <<  92.5;
+  *Power_Mixture_Correlation << 17 <<  88.0;
+  *Power_Mixture_Correlation << 18 <<  83.0;
+  *Power_Mixture_Correlation << 19 <<  78.5;
+  *Power_Mixture_Correlation << 20 <<  74.0;
+  *Power_Mixture_Correlation << (14.7/0.6) << 58;
+
+  // Read inputs from engine data file where present.
+
+  if (el->FindElement("minmp")) // Should have ELSE statement telling default value used?
+    MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG");
+  if (el->FindElement("maxmp"))
+    MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG");
+  if (el->FindElement("displacement"))
+    Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3");
+  if (el->FindElement("maxhp"))
+    MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP");
+  if (el->FindElement("cycles"))
+    Cycles = el->FindElementValueAsNumber("cycles");
+  if (el->FindElement("idlerpm"))
+    IdleRPM = el->FindElementValueAsNumber("idlerpm");
+  if (el->FindElement("maxthrottle"))
+    MaxThrottle = el->FindElementValueAsNumber("maxthrottle");
+  if (el->FindElement("minthrottle"))
+    MinThrottle = el->FindElementValueAsNumber("minthrottle");
+  if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
+    BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds");
+    if (el->FindElement("boostoverride"))
+      BoostOverride = (int)el->FindElementValueAsNumber("boostoverride");
+    if (el->FindElement("takeoffboost"))
+      TakeoffBoost = el->FindElementValueAsNumberConvertTo("takeoffboost", "PSI");
+    if (el->FindElement("ratedboost1"))
+      RatedBoost[0] = el->FindElementValueAsNumberConvertTo("ratedboost1", "PSI");
+    if (el->FindElement("ratedboost2"))
+      RatedBoost[1] = el->FindElementValueAsNumberConvertTo("ratedboost2", "PSI");
+    if (el->FindElement("ratedboost3"))
+      RatedBoost[2] = el->FindElementValueAsNumberConvertTo("ratedboost3", "PSI");
+    if (el->FindElement("ratedpower1"))
+      RatedPower[0] = el->FindElementValueAsNumberConvertTo("ratedpower1", "HP");
+    if (el->FindElement("ratedpower2"))
+      RatedPower[1] = el->FindElementValueAsNumberConvertTo("ratedpower2", "HP");
+    if (el->FindElement("ratedpower3"))
+      RatedPower[2] = el->FindElementValueAsNumberConvertTo("ratedpower3", "HP");
+    if (el->FindElement("ratedrpm1"))
+      RatedRPM[0] = el->FindElementValueAsNumber("ratedrpm1");
+    if (el->FindElement("ratedrpm2"))
+      RatedRPM[1] = el->FindElementValueAsNumber("ratedrpm2");
+    if (el->FindElement("ratedrpm3"))
+      RatedRPM[2] = el->FindElementValueAsNumber("ratedrpm3");
+    if (el->FindElement("ratedaltitude1"))
+      RatedAltitude[0] = el->FindElementValueAsNumberConvertTo("ratedaltitude1", "FT");
+    if (el->FindElement("ratedaltitude2"))
+      RatedAltitude[1] = el->FindElementValueAsNumberConvertTo("ratedaltitude2", "FT");
+    if (el->FindElement("ratedaltitude3"))
+      RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT");
+  }
+  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]) * psftopa;
+      //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() * psftopa + RatedBoost[i] * 6895;  // 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]) * psftopa);
+
+  }
+
+  if (BoostSpeeds > 0) {
+    Boosted = true;
+    BoostSpeed = 0;
+  }
+  bBoostOverride = (BoostOverride == 1 ? true : false);
+
+  Debug(0); // Call Debug() routine from constructor if needed
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPiston::~FGPiston()
+{
+  Debug(1); // Call Debug() routine from constructor if needed
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGPiston::Calculate(void)
+{
+  if (FuelFlow_gph > 0.0) ConsumeFuel();
+
+  Throttle = FCS->GetThrottlePos(EngineNumber);
+  Mixture = FCS->GetMixturePos(EngineNumber);
+
+  //
+  // Input values.
+  //
+
+  p_amb = Atmosphere->GetPressure() * psftopa;
+  p_amb_sea_level = Atmosphere->GetPressureSL() * psftopa;
+  T_amb = Atmosphere->GetTemperature() * (5.0 / 9.0);  // convert from Rankine to Kelvin
+
+  RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
+
+  IAS = Auxiliary->GetVcalibratedKTS();
+
+  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
+  //This might be a bit generous, but since there's currently no audiable warning of impending
+  //cutout in the form of misfiring and/or rough running its probably reasonable for now.
+  if (equivalence_ratio < 0.668)
+    Running = false;
+
+  doEnginePower();
+  doEGT();
+  doCHT();
+  doOilTemperature();
+  doOilPressure();
+
+  if (Thruster->GetType() == FGThruster::ttPropeller) {
+    ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
+  }
+
+  PowerAvailable = (HP * hptoftlbssec) - Thruster->GetPowerRequired();
+
+  return Thruster->Calculate(PowerAvailable);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/**
+ * Start or stop the engine.
+ */
+
+void FGPiston::doEngineStartup(void)
+{
+  // Check parameters that may alter the operating state of the engine.
+  // (spark, fuel, starter motor etc)
+  bool spark;
+  bool fuel;
+
+  // Check for spark
+  Magneto_Left = false;
+  Magneto_Right = false;
+  // Magneto positions:
+  // 0 -> off
+  // 1 -> left only
+  // 2 -> right only
+  // 3 -> both
+  if (Magnetos != 0) {
+    spark = true;
+  } 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;
+
+  // Assume we have fuel for now
+  fuel = !Starved;
+
+  // Check if we are turning the starter motor
+  if (Cranking != Starter) {
+    // This check saves .../cranking from getting updated every loop - they
+    // only update when changed.
+    Cranking = Starter;
+    crank_counter = 0;
+  }
+
+  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
+        Running = true;                         // on the starter
+    } else {
+      if (RPM > 450)                            // This allows us to in-air start
+        Running = true;                         // when windmilling
+    }
+  }
+
+  // Cut the engine *power* - Note: the engine may continue to
+  // spin if the prop is in a moving airstream
+
+  if ( Running && (!spark || !fuel) ) Running = false;
+
+  // Check for stalling (RPM = 0).
+  if (Running) {
+    if (RPM == 0) {
+      Running = false;
+    } else if ((RPM <= 480) && (Cranking)) {
+      Running = false;
+    }
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+/**
+ * Calculate the Current Boost Speed
+ *
+ * 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: minMAP, maxMAP, p_amb, Throttle
+ *
+ * Outputs: MAP, ManifoldPressure_inHg
+ */
+
+void FGPiston::doMAP(void)
+{
+  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 {
+    // rpm < 10 - effectively stopped.
+    // TODO - add a better variation of MAP with engine speed
+    MAP = Atmosphere->GetPressure() * psftopa;
+  }
+
+  // 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).
+ *
+ * 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 = 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;
+  m_dot_air = v_dot_air * rho_air_manifold;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/**
+ * Calculate the fuel flow into the engine.
+ *
+ * Inputs: Mixture, thi_sea_level, p_amb_sea_level, p_amb, m_dot_air
+ *
+ * Outputs: equivalence_ratio, m_dot_fuel
+ */
+
+void FGPiston::doFuelFlow(void)
+{
+  double thi_sea_level = 1.3 * Mixture;
+  equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb;
+  m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio;
+  FuelFlow_gph = m_dot_fuel
+    * 3600                     // seconds to hours
+    * 2.2046                   // kg to lb
+    / 6.6;                     // lb to gal_us of kerosene
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/**
+ * Calculate the power produced by the engine.
+ *
+ * Currently, the JSBSim propellor model does not allow the
+ * engine to produce enough RPMs to get up to a high horsepower.
+ * When tested with sufficient RPM, it has no trouble reaching
+ * 200HP.
+ *
+ * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb,
+ *   equivalence_ratio, Cycles, MaxHP
+ *
+ * Outputs: Percentage_Power, HP
+ */
+
+void FGPiston::doEnginePower(void)
+{
+  if (Running) {
+    double T_amb_degF = KelvinToFahrenheit(T_amb);
+    double T_amb_sea_lev_degF = KelvinToFahrenheit(288);
+
+    // FIXME: this needs to be generalized
+    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 (Boosted) {
+      HP = Percentage_Power * RatedPower[BoostSpeed] / 100.0;
+    } else {
+      HP = Percentage_Power * MaxHP / 100.0;
+    }
+
+  } else {
+
+    // Power output when the engine is not running
+    if (Cranking) {
+      if (RPM < 10) {
+        HP = 3.0;   // This is a hack to prevent overshooting the idle rpm in
+                    // 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);
+        // This is a guess - would be nice to find a proper starter moter torque curve
+      } else {
+        HP = 3.0;
+      }
+    } else {
+      // Quick hack until we port the FMEP stuff
+      if (RPM > 0.0)
+        HP = -1.5;
+      else
+        HP = 0.0;
+    }
+  }
+  //cout << "Power = " << HP << '\n';
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/**
+ * Calculate the exhaust gas temperature.
+ *
+ * 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
+ */
+
+void FGPiston::doEGT(void)
+{
+  double delta_T_exhaust;
+  double enthalpy_exhaust;
+  double heat_capacity_exhaust;
+  double dEGTdt;
+
+  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 *
+                              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;
+    ExhaustGasTemp_degK = T_amb + delta_T_exhaust;
+    ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * Percentage_Power / 100.0);
+  } else {  // Drop towards ambient - guess an appropriate time constant for now
+    dEGTdt = (298.0 - ExhaustGasTemp_degK) / 100.0;
+    delta_T_exhaust = dEGTdt * dt;
+    ExhaustGasTemp_degK += delta_T_exhaust;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/**
+ * Calculate the cylinder head temperature.
+ *
+ * Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel,
+ *   combustion_efficiency, RPM
+ *
+ * Outputs: CylinderHeadTemp_degK
+ */
+
+void FGPiston::doCHT(void)
+{
+  double h1 = -95.0;
+  double h2 = -3.95;
+  double h3 = -0.05;
+
+  double arbitary_area = 1.0;
+  double CpCylinderHead = 800.0;
+  double MassCylinderHead = 8.0;
+
+  double temperature_difference = CylinderHeadTemp_degK - T_amb;
+  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 =
+    m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;
+  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;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/**
+ * Calculate the oil temperature.
+ *
+ * Inputs: Percentage_Power, running flag.
+ *
+ * Outputs: OilTemp_degK
+ */
+
+void FGPiston::doOilTemperature(void)
+{
+  double idle_percentage_power = 2.3;        // approximately
+  double target_oil_temp;        // Steady state oil temp at the current engine conditions
+  double time_constant;          // The time constant for the differential equation
+
+  if (Running) {
+    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
+    }
+  } else {
+    target_oil_temp = 298;
+    time_constant = 1000;  // Time constant for engine-off; reflects the fact
+                           // that oil is no longer getting circulated
+  }
+
+  double dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant;
+
+  OilTemp_degK += (dOilTempdt * dt);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/**
+ * Calculate the oil pressure.
+ *
+ * Inputs: RPM
+ *
+ * Outputs: OilPressure_psi
+ */
+
+void FGPiston::doOilPressure(void)
+{
+  double Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine
+  double Oil_Press_RPM_Max = 1800;    // FIXME: may vary by engine
+  double Design_Oil_Temp = 358;              // degK; FIXME: may vary by engine
+  double Oil_Viscosity_Index = 0.25;
+
+  OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM;
+
+  if (OilPressure_psi >= Oil_Press_Relief_Valve) {
+    OilPressure_psi = Oil_Press_Relief_Valve;
+  }
+
+  OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPiston::GetEngineLabels(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_PwrAvail[" << EngineNumber << "]" << delimeter
+      << Name << "_HP[" << EngineNumber << "]" << delimeter
+      << Name << "_equiv_ratio[" << EngineNumber << "]" << delimeter
+      << Name << "_MAP[" << EngineNumber << "]" << delimeter
+      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPiston::GetEngineValues(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << PowerAvailable << delimeter << HP << delimeter
+      << equivalence_ratio << delimeter << MAP << delimeter
+      << Thruster->GetThrusterValues(EngineNumber, delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+//    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 FGPiston::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 << "      MinManifoldPressure: " << MinManifoldPressure_inHg << endl;
+      cout << "      MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl;
+      cout << "      MinMaP (Pa):         " << minMAP << endl;
+      cout << "      MaxMaP (Pa): "         << maxMAP << endl;
+      cout << "      Displacement: "        << Displacement             << endl;
+      cout << "      MaxHP: "               << MaxHP                    << endl;
+      cout << "      Cycles: "              << Cycles                   << endl;
+      cout << "      IdleRPM: "             << IdleRPM                  << endl;
+      cout << "      MaxThrottle: "         << MaxThrottle              << endl;
+      cout << "      MinThrottle: "         << MinThrottle              << endl;
+
+      cout << endl;
+      cout << "      Combustion Efficiency table:" << endl;
+      Lookup_Combustion_Efficiency->Print();
+      cout << endl;
+
+      cout << endl;
+      cout << "      Power Mixture Correlation table:" << endl;
+      Power_Mixture_Correlation->Print();
+      cout << endl;
+
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGPiston" << endl;
+    if (from == 1) cout << "Destroyed:    FGPiston" << 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
+FGPiston::CalcFuelNeed(void)
+{
+  return FuelFlow_gph / 3600 * 6 * State->Getdt() * Propulsion->GetRate();
+}
+
+} // namespace JSBSim
diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.h b/src/FDM/JSBSim/models/propulsion/FGPiston.h
new file mode 100644 (file)
index 0000000..3bb09ed
--- /dev/null
@@ -0,0 +1,273 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGPiston.h
+ Author:       Jon S. Berndt
+ Date started: 09/12/2000
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+09/12/2000  JSB  Created
+10/01/2001  DPM  Modified to use equations from Dave Luff's piston model.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGPISTON_H
+#define FGPISTON_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGEngine.h"
+#include <math/FGTable.h>
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_PISTON "$Id$";
+#define FG_MAX_BOOST_SPEEDS 3
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** 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 (initial porting and additional code)
+    @version $Id$
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGPiston : public FGEngine
+{
+public:
+  /// Constructor
+  FGPiston(FGFDMExec* exec, Element* el, int engine_number);
+  /// Destructor
+  ~FGPiston();
+
+  string GetEngineLabels(string delimeter);
+  string GetEngineValues(string delimeter);
+
+  double Calculate(void);
+  double GetPowerAvailable(void) {return PowerAvailable;}
+  double CalcFuelNeed(void);
+
+  void SetMagnetos(int magnetos) {Magnetos = magnetos;}
+
+  double  GetEGT(void) { return EGT_degC; }
+  int     GetMagnetos(void) {return Magnetos;}
+
+  double getExhaustGasTemp_degF(void) {return KelvinToFahrenheit(ExhaustGasTemp_degK);}
+  double getManifoldPressure_inHg(void) const {return ManifoldPressure_inHg;}
+  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;}
+
+private:
+  int crank_counter;
+
+  double BrakeHorsePower;
+  double SpeedSlope;
+  double SpeedIntercept;
+  double AltitudeSlope;
+  double PowerAvailable;
+
+  // timestep
+  double dt;
+
+  void doEngineStartup(void);
+  void doBoostControl(void);
+  void doMAP(void);
+  void doAirFlow(void);
+  void doFuelFlow(void);
+  void doEnginePower(void);
+  void doEGT(void);
+  void doCHT(void);
+  void doOilPressure(void);
+  void doOilTemperature(void);
+
+  //
+  // constants
+  //
+
+  const double R_air;
+  const double rho_fuel;    // kg/m^3
+  const double calorific_value_fuel;  // W/Kg (approximate)
+  const double Cp_air;      // J/KgK
+  const double Cp_fuel;     // J/KgK
+
+  FGTable *Lookup_Combustion_Efficiency;
+  FGTable *Power_Mixture_Correlation;
+
+  //
+  // Configuration
+  //
+  double MinManifoldPressure_inHg; // Inches Hg
+  double MaxManifoldPressure_inHg; // Inches Hg
+  double Displacement;             // cubic inches
+  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).
+  //
+  double p_amb;              // Pascals
+  double p_amb_sea_level;    // Pascals
+  double T_amb;              // degrees Kelvin
+  double RPM;                // revolutions per minute
+  double IAS;                // knots
+  bool Magneto_Left;
+  bool Magneto_Right;
+  int Magnetos;
+
+  //
+  // Outputs (in addition to those in FGEngine).
+  //
+  double rho_air;
+  double volumetric_efficiency;
+  double m_dot_air;
+  double equivalence_ratio;
+  double m_dot_fuel;
+  double Percentage_Power;
+  double HP;
+  double combustion_efficiency;
+  double ExhaustGasTemp_degK;
+  double EGT_degC;
+  double ManifoldPressure_inHg;
+  double CylinderHeadTemp_degK;
+  double OilPressure_psi;
+  double OilTemp_degK;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp b/src/FDM/JSBSim/models/propulsion/FGPropeller.cpp
new file mode 100644 (file)
index 0000000..40ef4a5
--- /dev/null
@@ -0,0 +1,382 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGPropeller.cpp
+ Author:       Jon S. Berndt
+ Date started: 08/24/00
+ Purpose:      Encapsulates the propeller object
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/24/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <sstream>
+
+#include "FGPropeller.h"
+#include <models/FGPropagate.h>
+#include <models/FGAtmosphere.h>
+#include <models/FGAuxiliary.h>
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_PROPELLER;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+// 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
+// helicopter.
+
+FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
+                       : FGThruster(exec, prop_element, num)
+{
+  string token;
+  int rows, cols;
+  Element *table_element, *local_element;
+  string name="";
+  FGPropertyManager* PropertyManager = exec->GetPropertyManager();
+
+  MaxPitch = MinPitch = P_Factor = Pitch = Advance = MinRPM = MaxRPM = 0.0;
+  Sense = 1; // default clockwise rotation
+  ReversePitch = 0.0;
+  Reversed = false;
+  Feathered = false;
+  Reverse_coef = 0.0;
+  GearRatio = 1.0;
+
+  if (prop_element->FindElement("ixx"))
+    Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
+  if (prop_element->FindElement("diameter"))
+    Diameter = prop_element->FindElementValueAsNumberConvertTo("diameter", "FT");
+  if (prop_element->FindElement("numblades"))
+    numBlades = (int)prop_element->FindElementValueAsNumber("numblades");
+  if (prop_element->FindElement("gearratio"))
+    GearRatio = prop_element->FindElementValueAsNumber("gearratio");
+  if (prop_element->FindElement("minpitch"))
+    MinPitch = prop_element->FindElementValueAsNumber("minpitch");
+  if (prop_element->FindElement("maxpitch"))
+    MaxPitch = prop_element->FindElementValueAsNumber("maxpitch");
+  if (prop_element->FindElement("minrpm"))
+    MinRPM = prop_element->FindElementValueAsNumber("minrpm");
+  if (prop_element->FindElement("maxrpm"))
+    MaxRPM = prop_element->FindElementValueAsNumber("maxrpm");
+  if (prop_element->FindElement("reversepitch"))
+    ReversePitch = prop_element->FindElementValueAsNumber("reversepitch");
+  for (int i=0; i<2; i++) {
+    table_element = prop_element->FindNextElement("table");
+    name = table_element->GetAttributeValue("name");
+    if (name == "C_THRUST") {
+      cThrust = new FGTable(PropertyManager, table_element);
+    } else if (name == "C_POWER") {
+      cPower = new FGTable(PropertyManager, table_element);
+    } else {
+      cerr << "Unknown table type: " << name << " in propeller definition." << endl;
+    }
+  }
+
+  local_element = prop_element->GetParent()->FindElement("sense");
+  if (local_element) {
+    double Sense = local_element->GetDataAsNumber();
+    SetSense(fabs(Sense)/Sense);
+  }
+  local_element = prop_element->GetParent()->FindElement("p_factor");
+  if (local_element) {
+    P_Factor = local_element->GetDataAsNumber();
+  }
+  if (P_Factor < 0) {
+    cerr << "P-Factor value in config file must be greater than zero" << endl;
+  }
+
+  Type = ttPropeller;
+  RPM = 0;
+  vTorque.InitMatrix();
+  D4 = Diameter*Diameter*Diameter*Diameter;
+  D5 = D4*Diameter;
+
+  char property_name[80];
+  snprintf(property_name, 80, "propulsion/engine[%d]/advance-ratio", EngineNum);
+  PropertyManager->Tie( property_name, &J );
+  snprintf(property_name, 80, "propulsion/engine[%d]/blade-angle", EngineNum);
+  PropertyManager->Tie( property_name, &Pitch );
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPropeller::~FGPropeller()
+{
+  if (cThrust)    delete cThrust;
+  if (cPower)     delete cPower;
+
+  char property_name[80];
+  snprintf(property_name, 80, "propulsion/engine[%d]/advance-ratio", EngineNum);
+  PropertyManager->Untie( property_name );
+  snprintf(property_name, 80, "propulsion/engine[%d]/blade-angle", EngineNum);
+  PropertyManager->Untie( property_name );
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// We must be getting the aerodynamic velocity here, NOT the inertial velocity.
+// We need the velocity with respect to the wind.
+//
+// Note that PowerAvailable is the excess power available after the drag of the
+// propeller has been subtracted. At equilibrium, PowerAvailable will be zero -
+// indicating that the propeller will not accelerate or decelerate.
+// Remembering that Torque * omega = Power, we can derive the torque on the
+// propeller and its acceleration to give a new RPM. The current RPM will be
+// used to calculate thrust.
+//
+// Because RPM could be zero, we need to be creative about what RPM is stated as.
+
+double FGPropeller::Calculate(double PowerAvailable)
+{
+  double omega, alpha, beta;
+
+  double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU);
+  double rho = fdmex->GetAtmosphere()->GetDensity();
+  double RPS = RPM/60.0;
+
+  if (RPS > 0.00) J = Vel / (Diameter * RPS); // Calculate J normally
+  else            J = 1000.0;                 // Set J to a high number
+
+  if (MaxPitch == MinPitch)  ThrustCoeff = cThrust->GetValue(J);
+  else                       ThrustCoeff = cThrust->GetValue(J, Pitch);
+
+  if (P_Factor > 0.0001) {
+    alpha = fdmex->GetAuxiliary()->Getalpha();
+    beta  = fdmex->GetAuxiliary()->Getbeta();
+    SetActingLocationY( GetLocationY() + P_Factor*alpha*Sense);
+    SetActingLocationZ( GetLocationZ() + P_Factor*beta*Sense);
+  }
+
+  Thrust = ThrustCoeff*RPS*RPS*D4*rho;
+  omega = RPS*2.0*M_PI;
+
+  vFn(1) = Thrust;
+
+  // The Ixx value and rotation speed given below are for rotation about the
+  // natural axis of the engine. The transform takes place in the base class
+  // FGForce::GetBodyForces() function.
+
+  vH(eX) = Ixx*omega*Sense;
+  vH(eY) = 0.0;
+  vH(eZ) = 0.0;
+
+  if (omega > 0.0) ExcessTorque = GearRatio * PowerAvailable / omega;
+  else             ExcessTorque = GearRatio * PowerAvailable / 1.0;
+
+  RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0;
+
+  if (RPM < 1.0) RPM = 0; // Engine friction stops rotation arbitrarily at 1 RPM.
+
+  vMn = fdmex->GetPropagate()->GetPQR()*vH + vTorque*Sense;
+
+  return Thrust; // return thrust in pounds
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGPropeller::GetPowerRequired(void)
+{
+  double cPReq, J;
+  double rho = fdmex->GetAtmosphere()->GetDensity();
+  double RPS = RPM / 60.0;
+
+  if (RPS != 0) J = fdmex->GetAuxiliary()->GetAeroUVW(eU) / (Diameter * RPS);
+  else          J = 1000.0; // Set J to a high number
+
+  if (MaxPitch == MinPitch) { // Fixed pitch prop
+    Pitch = MinPitch;
+    cPReq = cPower->GetValue(J);
+  } else {                      // Variable pitch prop
+
+    if (MaxRPM != MinRPM) {   // fixed-speed prop
+
+      // do normal calculation when propeller is neither feathered nor reversed
+      if (!Feathered) {
+        if (!Reversed) {
+
+          double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
+          double dRPM = rpmReq - RPM;
+          // The pitch of a variable propeller cannot be changed when the RPMs are
+          // too low - the oil pump does not work.
+          if (RPM > 200) Pitch -= dRPM / 10;
+
+          if (Pitch < MinPitch)       Pitch = MinPitch;
+          else if (Pitch > MaxPitch)  Pitch = MaxPitch;
+
+        } else { // Reversed propeller
+
+          // when reversed calculate propeller pitch depending on throttle lever position
+          // (beta range for taxing full reverse for braking)
+          double PitchReq = MinPitch - ( MinPitch - ReversePitch ) * Reverse_coef;
+          // The pitch of a variable propeller cannot be changed when the RPMs are
+          // too low - the oil pump does not work.
+          if (RPM > 200) Pitch += (PitchReq - Pitch) / 200;
+          if (RPM > MaxRPM) {
+            Pitch += (MaxRPM - RPM) / 50;
+            if (Pitch < ReversePitch) Pitch = ReversePitch;
+            else if (Pitch > MaxPitch)  Pitch = MaxPitch;
+          }
+        }
+
+      } else { // Feathered propeller
+               // ToDo: Make feathered and reverse settings done via FGKinemat
+        Pitch += (MaxPitch - Pitch) / 300; // just a guess (about 5 sec to fully feathered)
+      }
+
+    } else { // Variable Speed Prop
+      Pitch = MinPitch + (MaxPitch - MinPitch) * Advance;
+    }
+    cPReq = cPower->GetValue(J, Pitch);
+  }
+
+  if (RPS > 0) {
+    PowerRequired = cPReq*RPS*RPS*RPS*D5*rho;
+    vTorque(eX) = -Sense*PowerRequired / (RPS*2.0*M_PI);
+  } else {
+    PowerRequired = 0.0;
+    vTorque(eX) = 0.0;
+  }
+
+  return PowerRequired;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3 FGPropeller::GetPFactor()
+{
+  double px=0.0, py, pz;
+
+  py = Thrust * Sense * (GetActingLocationY() - GetLocationY()) / 12.0;
+  pz = Thrust * Sense * (GetActingLocationZ() - GetLocationZ()) / 12.0;
+
+  return FGColumnVector3(px, py, pz);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropeller::GetThrusterLabels(int id, string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_Torque[" << id << "]" << delimeter
+      << Name << "_PFactor_Pitch[" << id << "]" << delimeter
+      << Name << "_PFactor_Yaw[" << id << "]" << delimeter
+      << Name << "_Thrust[" << id << "]" << delimeter;
+  if (IsVPitch())
+    buf << Name << "_Pitch[" << id << "]" << delimeter;
+  buf << Name << "_RPM[" << id << "]";
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropeller::GetThrusterValues(int id, string delimeter)
+{
+  std::ostringstream buf;
+
+  FGColumnVector3 vPFactor = GetPFactor();
+  buf << vTorque(eX) << delimeter
+      << vPFactor(ePitch) << delimeter
+      << vPFactor(eYaw) << delimeter
+      << Thrust << delimeter;
+  if (IsVPitch())
+    buf << Pitch << delimeter;
+  buf << RPM;
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGPropeller::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "\n    Propeller Name: " << Name << endl;
+      cout << "      IXX = " << Ixx << endl;
+      cout << "      Diameter = " << Diameter << " ft." << endl;
+      cout << "      Number of Blades  = " << numBlades << endl;
+      cout << "      Gear Ratio  = " << GearRatio << endl;
+      cout << "      Minimum Pitch  = " << MinPitch << endl;
+      cout << "      Maximum Pitch  = " << MaxPitch << endl;
+      cout << "      Minimum RPM  = " << MinRPM << endl;
+      cout << "      Maximum RPM  = " << MaxRPM << endl;
+//      cout << "      Thrust Coefficient: " <<  endl;
+//      cThrust->Print();
+//      cout << "      Power Coefficient: " <<  endl;
+//      cPower->Print();
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGPropeller" << endl;
+    if (from == 1) cout << "Destroyed:    FGPropeller" << 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/models/propulsion/FGPropeller.h b/src/FDM/JSBSim/models/propulsion/FGPropeller.h
new file mode 100644 (file)
index 0000000..c0ddcde
--- /dev/null
@@ -0,0 +1,194 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGPropeller.h
+ Author:       Jon S. Berndt
+ Date started: 08/24/00
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/24/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGPROPELLER_H
+#define FGPROPELLER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGThruster.h"
+#include <math/FGTable.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_PROPELLER "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Propeller modeling class.
+    FGPropeller models a propeller given the tabular data for Ct and Cp
+    indexed by advance ratio "J". The data for the propeller is
+    stored in a config file named "prop_name.xml". The propeller config file
+    is referenced from the main aircraft config file in the "Propulsion" section.
+    See the constructor for FGPropeller to see what is read in and what should
+    be stored in the config file.<br>
+    Several references were helpful, here:<ul>
+    <li>Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
+     Wiley & Sons, 1979 ISBN 0-471-03032-5</li>
+    <li>Edwin Hartman, David Biermann, "The Aerodynamic Characteristics of
+    Full Scale Propellers Having 2, 3, and 4 Blades of Clark Y and R.A.F. 6
+    Airfoil Sections", NACA Report TN-640, 1938 (?)</li>
+    <li>Various NACA Technical Notes and Reports</li>
+    </ul>
+    @author Jon S. Berndt
+    @version $Id$
+    @see FGEngine
+    @see FGThruster
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGPropeller : public FGThruster {
+
+public:
+  /** Constructor for FGPropeller.
+      @param exec a pointer to the main executive object
+      @param el a pointer to the thruster config file XML element*/
+  FGPropeller(FGFDMExec* exec, Element* el, int num = 0);
+
+  /// Destructor for FGPropeller - deletes the FGTable objects
+  ~FGPropeller();
+
+  /** Sets the Revolutions Per Minute for the propeller. Normally the propeller
+      instance will calculate its own rotational velocity, given the Torque
+      produced by the engine and integrating over time using the standard
+      equation for rotational acceleration "a": a = Q/I , where Q is Torque and
+      I is moment of inertia for the propeller.
+      @param rpm the rotational velocity of the propeller */
+  void SetRPM(double rpm) {RPM = rpm;}
+
+  /// Returns true of this propeller is variable pitch
+  bool IsVPitch(void) {return MaxPitch != MinPitch;}
+
+  /** This commands the pitch of the blade to change to the value supplied.
+      This call is meant to be issued either from the cockpit or by the flight
+      control system (perhaps to maintain constant RPM for a constant-speed
+      propeller). This value will be limited to be within whatever is specified
+      in the config file for Max and Min pitch. It is also one of the lookup
+      indices to the power and thrust tables for variable-pitch propellers.
+      @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;}
+
+  /** Sets the rotation sense of the propeller.
+      @param s this value should be +/- 1 ONLY. +1 indicates clockwise rotation as
+               viewed by someone standing behind the engine looking forward into
+               the direction of flight. */
+  void SetSense(double s) { Sense = s;}
+
+  /// 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
+      the torque provided by the engine over what the propeller "absorbs"
+      (essentially the "drag" of the propeller).
+      @param PowerAvailable this is the excess power provided by the engine to
+      accelerate the prop. It could be negative, dictating that the propeller
+      would be slowed.
+      @return the thrust in pounds */
+  double Calculate(double PowerAvailable);
+  FGColumnVector3 GetPFactor(void);
+  string GetThrusterLabels(int id, string delimeter);
+  string GetThrusterValues(int id, string delimeter);
+
+  void   SetReverseCoef (double c) { Reverse_coef = c; }
+  double GetReverseCoef (void) { return Reverse_coef; }
+  void   SetReverse (bool r) { Reversed = r; }
+  bool   GetReverse (void) { return Reversed; }
+  void   SetFeather (bool f) { Feathered = f; }
+  bool   GetFeather (void) { return Feathered; }
+
+private:
+  int   numBlades;
+  double J;
+  double RPM;
+  double Ixx;
+  double Diameter;
+  double MaxPitch;
+  double MinPitch;
+  double MinRPM;
+  double MaxRPM;
+  double Pitch;
+  double P_Factor;
+  double Sense;
+  double Advance;
+  double ExcessTorque;
+  double D4;
+  double D5;
+  FGColumnVector3 vTorque;
+  FGTable *cThrust;
+  FGTable *cPower;
+  void Debug(int from);
+  double ReversePitch; // Pitch, when fully reversed
+  bool   Reversed;              // true, when propeller is reversed
+  double Reverse_coef; // 0 - 1 defines AdvancePitch (0=MIN_PITCH 1=REVERSE_PITCH)
+  bool   Feathered;    // true, if feather command
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp
new file mode 100644 (file)
index 0000000..2bcbcca
--- /dev/null
@@ -0,0 +1,195 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGRocket.cpp
+ Author:       Jon S. Berndt
+ Date started: 09/12/2000
+ Purpose:      This module models a rocket engine
+
+ ------------- Copyright (C) 2000  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 descends from the FGEngine class and models a rocket engine based on
+parameters given in the engine config file for this class
+
+HISTORY
+--------------------------------------------------------------------------------
+09/12/2000  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <sstream>
+
+#include "FGRocket.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_ROCKET;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
+  : FGEngine(exec, el, engine_number)
+{
+  if (el->FindElement("shr"))
+    SHR = el->FindElementValueAsNumber("shr");
+  if (el->FindElement("max_pc"))
+    maxPC = el->FindElementValueAsNumberConvertTo("max_pc", "PSF");
+  if (el->FindElement("prop_eff"))
+    propEff = el->FindElementValueAsNumber("prop_eff");
+  if (el->FindElement("maxthrottle"))
+    MaxThrottle = el->FindElementValueAsNumber("maxthrottle");
+  if (el->FindElement("minthrottle"))
+    MinThrottle = el->FindElementValueAsNumber("minthrottle");
+  if (el->FindElement("slfuelflowmax"))
+    SLFuelFlowMax = el->FindElementValueAsNumberConvertTo("slfuelflowmax", "LBS/SEC");
+  if (el->FindElement("sloxiflowmax"))
+    SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC");
+  if (el->FindElement("variance"))
+    Variance = el->FindElementValueAsNumber("variance");
+
+  Debug(0);
+
+  Type = etRocket;
+  Flameout = false;
+
+  PC = 0.0;
+  kFactor = (2.0*SHR*SHR/(SHR-1.0))*pow(2.0/(SHR+1), (SHR+1)/(SHR-1));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGRocket::~FGRocket(void)
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGRocket::Calculate(void)
+{
+  double Cf=0;
+
+  if (!Flameout && !Starved) ConsumeFuel();
+
+  Throttle = FCS->GetThrottlePos(EngineNumber);
+
+  if (Throttle < MinThrottle || Starved) {
+    PctPower = Thrust = 0.0; // desired thrust
+    Flameout = true;
+    PC = 0.0;
+  } else {
+    PctPower = Throttle / MaxThrottle;
+    //todo: remove Variance?
+    PC = maxPC*PctPower * (1.0 + Variance * ((double)rand()/(double)RAND_MAX - 0.5));
+    // The Cf (below) is CF from Eqn. 3-30, "Rocket Propulsion Elements", Fifth Edition,
+    // George P. Sutton. Note that the thruster function GetPowerRequired() might
+    // be better called GetResistance() or something; this function returns the
+    // nozzle exit pressure.
+    Cf = sqrt(kFactor*(1 - pow(Thruster->GetPowerRequired()/(PC), (SHR-1)/SHR)));
+    Flameout = false;
+  }
+
+  return Thruster->Calculate(Cf*maxPC*PctPower*propEff);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRocket::GetEngineLabels(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_ChamberPress[" << EngineNumber << "]" << delimeter
+      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRocket::GetEngineValues(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << PC << delimeter << Thruster->GetThrusterValues(EngineNumber, delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGRocket::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "      Engine Name: " << Name << endl;
+      cout << "      Specific Heat Ratio = " << SHR << endl;
+      cout << "      Maximum Chamber Pressure = " << maxPC << endl;
+      cout << "      Propulsive Efficiency = " << propEff << endl;
+      cout << "      MaxThrottle = " << MaxThrottle << endl;
+      cout << "      MinThrottle = " << MinThrottle << endl;
+      cout << "      FuelFlowMax = " << SLFuelFlowMax << endl;
+      cout << "      OxiFlowMax = " << SLOxiFlowMax << endl;
+      cout << "      Variance = " << Variance << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGRocket" << endl;
+    if (from == 1) cout << "Destroyed:    FGRocket" << 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/models/propulsion/FGRocket.h b/src/FDM/JSBSim/models/propulsion/FGRocket.h
new file mode 100644 (file)
index 0000000..d21ad4c
--- /dev/null
@@ -0,0 +1,143 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGRocket.h
+ Author:       Jon S. Berndt
+ Date started: 09/12/2000
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+09/12/2000  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGROCKET_H
+#define FGROCKET_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGEngine.h"
+#include <input_output/FGXMLElement.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_ROCKET "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models a generic rocket engine.
+    The rocket engine is modeled given the following parameters:
+    <ul>
+        <li>Chamber pressure (in psf)</li>
+        <li>Specific heat ratio (usually about 1.2 for hydrocarbon fuel and LOX)</li>
+        <li>Propulsive efficiency (in percent, from 0 to 1.0)</li>
+        <li>Variance (in percent, from 0 to 1.0, nominally 0.05)</li>
+    </ul>
+    Additionally, the following control inputs, operating characteristics, and
+    location are required, as with all other engine types:
+    <ul>
+        <li>Throttle setting (in percent, from 0 to 1.0)</li>
+        <li>Maximum allowable throttle setting</li>
+        <li>Minimum working throttle setting</li>
+        <li>Sea level fuel flow at maximum thrust</li>
+        <li>Sea level oxidizer flow at maximum thrust</li>
+        <li>X, Y, Z location in structural coordinate frame</li>
+        <li>Pitch and Yaw</li>
+    </ul>
+    The nozzle exit pressure (p2) is returned via a
+    call to FGNozzle::GetPowerRequired(). This exit pressure is used,
+    along with chamber pressure and specific heat ratio, to get the
+    thrust coefficient for the throttle setting. This thrust
+    coefficient is multiplied by the chamber pressure and then passed
+    to the nozzle Calculate() routine, where the thrust force is
+    determined.
+
+    @author Jon S. Berndt
+    $Id$
+    @see FGNozzle,
+    FGThruster,
+    FGForce,
+    FGEngine,
+    FGPropulsion,
+    FGTank
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGRocket : public FGEngine
+{
+public:
+  /** Constructor.
+      @param exec pointer to JSBSim parent object, the FDM Executive.
+      @param el a pointer to the XML Element instance representing the engine.
+      @param engine_number engine number */
+  FGRocket(FGFDMExec* exec, Element *el, int engine_number);
+
+  /** Destructor */
+  ~FGRocket(void);
+
+  /** Determines the thrust coefficient.
+      @return thrust coefficient times chamber pressure */
+  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
+      sustainable setting.
+      @return true if engine has flamed out. */
+  bool GetFlameout(void) {return Flameout;}
+  string GetEngineLabels(string delimeter);
+  string GetEngineValues(string delimeter);
+
+private:
+  double SHR;
+  double maxPC;
+  double propEff;
+  double kFactor;
+  double Variance;
+  double PC;
+  bool Flameout;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGRotor.cpp b/src/FDM/JSBSim/models/propulsion/FGRotor.cpp
new file mode 100644 (file)
index 0000000..b1efdde
--- /dev/null
@@ -0,0 +1,128 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGRotor.cpp
+ Author:       Jon S. Berndt
+ Date started: 08/24/00
+ Purpose:      Encapsulates the rotor object
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/24/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGRotor.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_ROTOR;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGRotor::FGRotor(FGFDMExec *FDMExec) : FGThruster(FDMExec)
+{
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGRotor::~FGRotor()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGRotor::Calculate(double PowerAvailable)
+{
+  return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRotor::GetThrusterLabels(int id, string delimeter)
+{
+  return "";
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGRotor::GetThrusterValues(int id, string delimeter)
+{
+  return "";
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGRotor::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: FGRotor" << endl;
+    if (from == 1) cout << "Destroyed:    FGRotor" << 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/models/propulsion/FGRotor.h b/src/FDM/JSBSim/models/propulsion/FGRotor.h
new file mode 100644 (file)
index 0000000..2e4b3b3
--- /dev/null
@@ -0,0 +1,81 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGRotor.h
+ Author:       Jon S. Berndt
+ Date started: 08/24/00
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/24/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGROTOR_H
+#define FGROTOR_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGThruster.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_ROTOR "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models a rotor (such as for a helicopter); NOT YET IMPLEMENTED.
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGRotor : public FGThruster {
+
+public:
+  FGRotor(FGFDMExec *FDMExec);
+  ~FGRotor();
+
+  double Calculate(double);
+  string GetThrusterLabels(int id, string delimeter);
+  string GetThrusterValues(int id, string delimeter);
+
+private:
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/models/propulsion/FGTank.cpp b/src/FDM/JSBSim/models/propulsion/FGTank.cpp
new file mode 100644 (file)
index 0000000..57bebd7
--- /dev/null
@@ -0,0 +1,220 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGTank.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
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <FGFDMExec.h>
+#include <models/FGAuxiliary.h>
+#include "FGTank.h"
+
+#if !defined ( sgi ) || defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
+using std::cerr;
+using std::endl;
+using std::cout;
+#endif
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_TANK;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGTank::FGTank(FGFDMExec* exec, Element* el)
+{
+  string token;
+  Element* element;
+  Area = 1.0;
+  Temperature = -9999.0;
+  Auxiliary = exec->GetAuxiliary();
+  Radius = Capacity = Contents = 0.0;
+
+  type = el->GetAttributeValue("type");
+  if      (type == "FUEL")     Type = ttFUEL;
+  else if (type == "OXIDIZER") Type = ttOXIDIZER;
+  else                         Type = ttUNKNOWN;
+
+  element = el->FindElement("location");
+  if (element)  vXYZ = element->FindElementTripletConvertTo("IN");
+  else          cerr << "No location found for this tank." << endl;
+
+  if (el->FindElement("radius"))
+    Radius = el->FindElementValueAsNumberConvertTo("radius", "IN");
+  if (el->FindElement("capacity"))
+    Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS");
+  if (el->FindElement("contents"))
+    Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS");
+  if (el->FindElement("temperature"))
+    Temperature = el->FindElementValueAsNumber("temperature");
+
+  Selected = true;
+
+  if (Capacity != 0) {
+    PctFull = 100.0*Contents/Capacity;            // percent full; 0 to 100.0
+  } else {
+    Contents = 0;
+    PctFull  = 0;
+  }
+
+  if (Temperature != -9999.0)  Temperature = FahrenheitToCelsius(Temperature);
+  Area = 40.0 * pow(Capacity/1975, 0.666666667);
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTank::~FGTank()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTank::Drain(double used)
+{
+  double shortage = Contents - used;
+
+  if (shortage >= 0) {
+    Contents -= used;
+    PctFull = 100.0*Contents/Capacity;
+  } else {
+    Contents = 0.0;
+    PctFull = 0.0;
+    Selected = false;
+  }
+  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
+//       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 FGTank::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+      cout << "      " << type << " tank holds " << Capacity << " lbs. " << type << endl;
+      cout << "      currently at " << PctFull << "% of maximum capacity" << endl;
+      cout << "      Tank location (X, Y, Z): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl;
+      cout << "      Effective radius: " << Radius << " inches" << endl;
+      cout << "      Initial temperature: " << Temperature << " Fahrenheit" << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGTank" << endl;
+    if (from == 1) cout << "Destroyed:    FGTank" << 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/models/propulsion/FGTank.h b/src/FDM/JSBSim/models/propulsion/FGTank.h
new file mode 100644 (file)
index 0000000..33e3430
--- /dev/null
@@ -0,0 +1,174 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGTank.h
+ Author:       Jon S. Berndt
+ Date started: 01/21/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.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+Based on Flightgear code, which is based on LaRCSim. This class simulates
+a generic Tank.
+
+HISTORY
+--------------------------------------------------------------------------------
+01/21/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGTank_H
+#define FGTank_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <FGJSBBase.h>
+#include <input_output/FGXMLElement.h>
+#include <math/FGColumnVector3.h>
+// #include <FGAuxiliary.h>
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  include STL_STRING
+  SG_USING_STD(string);
+  SG_USING_STD(cerr);
+  SG_USING_STD(endl);
+  SG_USING_STD(cout);
+#else
+# include <string>
+  using std::string;
+# if !defined(sgi) || defined(__GNUC__) || (_COMPILER_VERSION >= 740)
+   using std::cerr;
+   using std::endl;
+   using std::cout;
+# endif
+#endif
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_TANK "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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>
+  */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGTank : public FGJSBBase
+{
+public:
+  FGTank(FGFDMExec* exec, Element* el);
+  ~FGTank();
+
+  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);}
+
+  double Fill(double amount);
+  void SetContents(double amount);
+  void SetTemperature(double temp) { Temperature = temp; }
+
+  enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER};
+
+private:
+  TankType Type;
+  string type;
+  FGColumnVector3 vXYZ;
+  double Capacity;
+  double Radius;
+  double PctFull;
+  double Contents;
+  double Area;
+  double Temperature;      
+  bool  Selected;
+  FGAuxiliary* Auxiliary;
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGThruster.cpp b/src/FDM/JSBSim/models/propulsion/FGThruster.cpp
new file mode 100644 (file)
index 0000000..9d1dc33
--- /dev/null
@@ -0,0 +1,181 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGThruster.cpp
+ Author:       Jon S. Berndt
+ Date started: 08/23/00
+ Purpose:      Encapsulates the thruster object
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/23/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <sstream>
+
+#include "FGThruster.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_THRUSTER;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGThruster::FGThruster(FGFDMExec *FDMExec) : FGForce(FDMExec)
+{
+  Type = ttDirect;
+  SetTransformType(FGForce::tCustom);
+
+  EngineNum = 0;
+  PropertyManager = FDMExec->GetPropertyManager();
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMExec)
+{
+  Element* thruster_element = el->GetParent();
+  Element* element;
+  FGColumnVector3 location, orientation;
+
+  Type = ttDirect;
+  SetTransformType(FGForce::tCustom);
+
+  Name = el->GetName();
+
+  GearRatio = 1.0;
+
+  EngineNum = num;
+  ThrustCoeff = 0.0;
+  PropertyManager = FDMExec->GetPropertyManager();
+
+// Determine the initial location and orientation of this thruster and load the
+// thruster with this information.
+
+  element = thruster_element->FindElement("location");
+  if (element)  location = element->FindElementTripletConvertTo("IN");
+  else          cerr << "No thruster location found." << endl;
+
+  element = thruster_element->FindElement("orient");
+  if (element)  orientation = element->FindElementTripletConvertTo("IN");
+  else          cerr << "No thruster orientation found." << endl;
+
+  SetLocation(location);
+  SetAnglesToBody(orientation);
+
+//  char property_name[80];
+//  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
+//  PropertyManager->Tie( property_name, &ThrustCoeff );
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGThruster::~FGThruster()
+{
+//  char property_name[80];
+//  snprintf(property_name, 80, "propulsion/c-thrust[%u]", EngineNum);
+//  PropertyManager->Untie( property_name );
+
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGThruster::GetThrusterLabels(int id, string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_Thrust[" << id << "]";
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGThruster::GetThrusterValues(int id, string delimeter)
+{
+  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
+//       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 FGThruster::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: FGThruster" << endl;
+    if (from == 1) cout << "Destroyed:    FGThruster" << 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/models/propulsion/FGThruster.h b/src/FDM/JSBSim/models/propulsion/FGThruster.h
new file mode 100644 (file)
index 0000000..8c6e6da
--- /dev/null
@@ -0,0 +1,116 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGThruster.h
+ Author:       Jon S. Berndt
+ Date started: 08/23/00
+
+ ------------- Copyright (C) 2000  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
+--------------------------------------------------------------------------------
+08/24/00  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGTHRUSTER_H
+#define FGTHRUSTER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGForce.h"
+#include <input_output/FGXMLElement.h>
+#include <input_output/FGPropertyManager.h>
+#include <math/FGColumnVector3.h>
+#include <string>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_THRUSTER "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Base class for specific thrusting devices such as propellers, nozzles, etc.
+    @author Jon Berndt
+    @version $Id$
+    */
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGThruster : public FGForce {
+
+public:
+  /// Constructor
+  FGThruster(FGFDMExec *FDMExec);
+  FGThruster(FGFDMExec *FDMExec, Element *el, int num );
+  /// Destructor
+  virtual ~FGThruster();
+
+  enum eType {ttNozzle, ttRotor, ttPropeller, ttDirect};
+
+  virtual double Calculate(double tt) {
+       Thrust = tt; vFn(1) = Thrust;
+       return Thrust;
+  }
+  void SetName(string name) {Name = name;}
+  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;}
+  virtual double GetRPM(void) { return 0.0; };
+  double GetGearRatio(void) {return GearRatio; }
+  virtual string GetThrusterLabels(int id, string delimeter);
+  virtual string GetThrusterValues(int id, string delimeter);
+
+  inline void SetThrustCoefficient(double ct) { ThrustCoeff = ct; }
+
+protected:
+  eType Type;
+  string Name;
+  double Thrust;
+  double PowerRequired;
+  double deltaT;
+  double GearRatio;
+  double ThrustCoeff;
+  int EngineNum;
+  FGPropertyManager* PropertyManager;
+  virtual void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
new file mode 100644 (file)
index 0000000..9554e55
--- /dev/null
@@ -0,0 +1,578 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGTurbine.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 <sstream>
+
+#include "FGTurbine.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_TURBINE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number)
+  : FGEngine(exec, el, engine_number)
+{
+  SetDefaults();
+
+  Load(exec, el);
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTurbine::~FGTurbine()
+{
+  if (IdleThrustLookup) delete IdleThrustLookup;
+  if (MilThrustLookup) delete MilThrustLookup;
+  if (MaxThrustLookup) delete MaxThrustLookup;
+  if (InjectionLookup) delete InjectionLookup;
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// The main purpose of Calculate() is to determine what phase the engine should
+// be in, then call the corresponding function.
+
+double FGTurbine::Calculate(void)
+{
+  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 {
+    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();
+  }
+
+  Thrust = Thruster->Calculate(Thrust); // allow thruster to modify thrust (i.e. reversing)
+
+  return Thrust;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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::Run()
+{
+  double idlethrust, milthrust, thrust;
+  double N2norm;   // 0.0 = idle N2, 1.0 = maximum N2
+
+  idlethrust = MilThrust * IdleThrustLookup->GetValue();
+  milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
+
+  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) {
+    correctedTSFC = TSFC * (0.84 + (1-N2norm)*(1-N2norm));
+    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 = MaxThrustLookup->GetValue() * MaxThrust;
+    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
+    NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
+  }
+
+  if (AugMethod == 2) {
+    if (AugmentCmd > 0.0) {
+      Augmentation = true;
+      double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - 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 {
+      Augmentation = false;
+    }
+  }
+
+  if ((Injected == 1) && Injection) {
+    thrust = thrust * InjectionLookup->GetValue();
+  }
+
+  ConsumeFuel();
+  if (Cutoff) phase = tpOff;
+  if (Starved) phase = tpOff;
+
+  return thrust;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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;
+      ConsumeFuel();
+      }
+    else {
+      phase = tpRun;
+      Running = true;
+      Starter = false;
+      Cranking = false;
+      }
+    }
+  else {                 // no start if N2 < 15%
+    phase = tpOff;
+    Starter = false;
+    }
+
+  return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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);
+  ConsumeFuel();
+  if (ThrottlePos < 0.01) phase = tpRun;        // clear the stall with throttle
+
+  return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurbine::Seize(void)
+{
+    double qbar = Auxiliary->Getqbar();
+    N2 = 0.0;
+    N1 = Seek(&N1, qbar/20.0, 0, N1/15.0);
+    FuelFlow_pph = IdleFF;
+    ConsumeFuel();
+    OilPressure_psi = 0.0;
+    OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0, 0.2);
+    Running = false;
+    return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurbine::Trim()
+{
+    double idlethrust, milthrust, thrust, tdiff;
+    idlethrust = MilThrust * IdleThrustLookup->GetValue();
+    milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
+    thrust = (idlethrust + (milthrust * ThrottlePos * ThrottlePos))
+          * (1.0 - BleedDemand);
+
+    if (AugMethod == 1) {
+      if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;}
+      else {Augmentation = false;}
+    }
+
+    if ((Augmented == 1) && Augmentation && (AugMethod < 2)) {
+      thrust = MaxThrust * MaxThrustLookup->GetValue();
+    }
+
+    if (AugMethod == 2) {
+      if (AugmentCmd > 0.0) {
+        tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust;
+        thrust += (tdiff * AugmentCmd);
+      }
+    }
+
+    if ((Injected == 1) && Injection) {
+      thrust = thrust * InjectionLookup->GetValue();
+    }
+
+    return thrust;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurbine::CalcFuelNeed(void)
+{
+  return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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)
+{
+  N1 = N2 = 0.0;
+  Type = etTurbine;
+  MilThrust = 10000.0;
+  MaxThrust = 10000.0;
+  BypassRatio = 0.0;
+  TSFC = 0.8;
+  correctedTSFC = TSFC;
+  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;
+  IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGTurbine::Load(FGFDMExec* exec, Element *el)
+{
+  char property_prefix[80];
+  snprintf(property_prefix, 80, "propulsion/engine[%u]/", EngineNumber);
+
+  if (el->FindElement("milthrust"))
+    MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS");
+  if (el->FindElement("maxthrust"))
+    MaxThrust = el->FindElementValueAsNumberConvertTo("maxthrust","LBS");
+  if (el->FindElement("bypassratio"))
+    BypassRatio = el->FindElementValueAsNumber("bypassratio");
+  if (el->FindElement("bleed"))
+    BleedDemand = el->FindElementValueAsNumber("bleed");
+  if (el->FindElement("tsfc"))
+    TSFC = el->FindElementValueAsNumber("tsfc");
+  if (el->FindElement("atsfc"))
+    ATSFC = el->FindElementValueAsNumber("atsfc");
+  if (el->FindElement("idlen1"))
+    IdleN1 = el->FindElementValueAsNumber("idlen1");
+  if (el->FindElement("idlen2"))
+    IdleN2 = el->FindElementValueAsNumber("idlen2");
+  if (el->FindElement("maxn1"))
+    MaxN1 = el->FindElementValueAsNumber("maxn1");
+  if (el->FindElement("maxn2"))
+    MaxN2 = el->FindElementValueAsNumber("maxn2");
+  if (el->FindElement("augmented"))
+    Augmented = (int)el->FindElementValueAsNumber("augmented");
+  if (el->FindElement("augmethod"))
+    AugMethod = (int)el->FindElementValueAsNumber("augmethod");
+  if (el->FindElement("injected"))
+    Injected = (int)el->FindElementValueAsNumber("injected");
+
+  Element *function_element;
+  string name;
+  FGPropertyManager* PropertyManager = exec->GetPropertyManager();
+
+  while (true) {
+    function_element = el->FindNextElement("function");
+    if (!function_element) break;
+    name = function_element->GetAttributeValue("name");
+    if (name == "IdleThrust") {
+      IdleThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix);
+    } else if (name == "MilThrust") {
+      MilThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix);
+    } else if (name == "AugThrust") {
+      MaxThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix);
+    } else if (name == "Injection") {
+      InjectionLookup = new FGFunction(PropertyManager, function_element, property_prefix);
+    } else {
+      cerr << "Unknown function type: " << name << " in turbine definition." <<
+      endl;
+    }
+  }
+
+  // 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
+
+  bindmodel();
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGTurbine::GetEngineLabels(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_N1[" << EngineNumber << "]" << delimeter
+      << Name << "_N2[" << EngineNumber << "]" << delimeter
+      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGTurbine::GetEngineValues(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << N1 << delimeter
+      << N2 << delimeter
+      << Thruster->GetThrusterValues(EngineNumber, delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTurbine::bindmodel()
+{
+  char property_name[80];
+
+  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
+  PropertyManager->Tie( property_name, &N1);
+  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
+  PropertyManager->Tie( property_name, &N2);
+  snprintf(property_name, 80, "propulsion/engine[%u]/thrust", EngineNumber);
+  PropertyManager->Tie( property_name, this, &FGTurbine::GetThrust);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTurbine::unbind()
+{
+  char property_name[80];
+
+  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
+  PropertyManager->Untie(property_name);
+  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
+  PropertyManager->Untie(property_name);
+  snprintf(property_name, 80, "propulsion/engine[%u]/thrust", EngineNumber);
+  PropertyManager->Untie(property_name);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGTurbine::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: FGTurbine" << endl;
+    if (from == 1) cout << "Destroyed:    FGTurbine" << 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/models/propulsion/FGTurbine.h b/src/FDM/JSBSim/models/propulsion/FGTurbine.h
new file mode 100644 (file)
index 0000000..0b2740d
--- /dev/null
@@ -0,0 +1,257 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGTurbine.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
+04/29/2004  DPC  Renamed from FGSimTurbine to FGTurbine
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGTURBINE_H
+#define FGTURBINE_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <vector>
+#include "FGEngine.h"
+#include <input_output/FGXMLElement.h>
+#include <math/FGFunction.h>
+
+#define ID_TURBINE "$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_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
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGTurbine : public FGEngine
+{
+public:
+  /** Constructor
+      @param Executive pointer to executive structure
+      @param el pointer to the XML element representing the turbine engine
+      @param engine_number engine number*/
+  FGTurbine(FGFDMExec* Executive, Element *el, int engine_number);
+  /// Destructor
+  ~FGTurbine();
+
+  enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
+
+  double Calculate(void);
+  double CalcFuelNeed(void);
+  double GetPowerAvailable(void);
+  double GetThrust(void) const {return Thrust;}
+  double Seek(double* var, double target, double accel, double decel);
+
+  phaseType GetPhase(void) { return phase; }
+
+  bool GetOvertemp(void)  const {return Overtemp; }
+  bool GetInjection(void) const {return Injection;}
+  bool GetFire(void) const { return Fire; }
+  bool GetAugmentation(void) const {return Augmentation;}
+  bool GetReversed(void) const { return Reversed; }
+  bool GetCutoff(void) const { return Cutoff; }
+  int GetIgnition(void) const {return Ignition;}
+
+  double GetInlet(void) const { return InletPosition; }
+  double GetNozzle(void) const { return NozzlePosition; }
+  double GetBleedDemand(void) const {return BleedDemand;}
+  double GetN1(void) const {return N1;}
+  double GetN2(void) const {return N2;}
+  double GetEPR(void) const {return EPR;}
+  double GetEGT(void) const {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(string delimeter);
+  string GetEngineValues(string delimeter);
+
+private:
+
+  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 correctedTSFC;
+
+  double Off(void);
+  double Run();
+  double SpinUp(void);
+  double Start(void);
+  double Stall(void);
+  double Seize(void);
+  double Trim();
+
+  FGFunction *IdleThrustLookup;
+  FGFunction *MilThrustLookup;
+  FGFunction *MaxThrustLookup;
+  FGFunction *InjectionLookup;
+
+  void SetDefaults(void);
+  bool Load(FGFDMExec *exec, Element *el);
+  void bindmodel(void);
+  void unbind(void);
+  void Debug(int from);
+
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
new file mode 100755 (executable)
index 0000000..e6bd2dc
--- /dev/null
@@ -0,0 +1,578 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGTurboProp.cpp
+ Author:       Jiri "Javky" Javurek
+               based on SimTurbine and Turbine engine from David Culp
+ Date started: 05/14/2004
+ Purpose:      This module models a turbo propeller engine.
+
+ ------------- Copyright (C) 2004  (javky@email.cz) ---------
+
+ 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 Turbo propeller engine
+based on parameters given in the engine config file for this class
+
+HISTORY
+--------------------------------------------------------------------------------
+05/14/2004  Created
+
+//JVK (mark)
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <vector>
+#include <sstream>
+#include "FGTurboProp.h"
+
+#include "FGPropeller.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_TURBOPROP;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number)
+  : FGEngine(exec, el, engine_number)
+{
+  SetDefaults();
+
+  Load(exec, el);
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGTurboProp::~FGTurboProp()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
+{
+  char property_prefix[80];
+  snprintf(property_prefix, 80, "propulsion/engine[%u]/", EngineNumber);
+
+  IdleFF=-1;
+  MaxStartingTime = 999999; //very big timeout -> infinite
+  Ielu_max_torque=-1;
+
+// ToDo: Need to make sure units are properly accounted for below.
+
+  if (el->FindElement("milthrust"))
+    MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS");
+  if (el->FindElement("idlen1"))
+    IdleN1 = el->FindElementValueAsNumber("idlen1");
+  if (el->FindElement("idlen2"))
+    IdleN2 = el->FindElementValueAsNumber("idlen1");
+  if (el->FindElement("maxn1"))
+    MaxN1 = el->FindElementValueAsNumber("maxn1");
+  if (el->FindElement("maxn2"))
+    MaxN2 = el->FindElementValueAsNumber("maxn2");
+  if (el->FindElement("betarangeend"))
+    BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0;
+  if (el->FindElement("reversemaxpower"))
+    ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0;
+
+  if (el->FindElement("maxpower"))
+    MaxPower = el->FindElementValueAsNumber("maxpower");
+  if (el->FindElement("idlefuelflow"))
+    IdleFF = el->FindElementValueAsNumber("idlefuelflow");
+  if (el->FindElement("psfc"))
+    PSFC = el->FindElementValueAsNumber("psfc");
+  if (el->FindElement("n1idle_max_delay"))
+    Idle_Max_Delay = el->FindElementValueAsNumber("n1idle_max_delay");
+  if (el->FindElement("maxstartingtime"))
+    MaxStartingTime = el->FindElementValueAsNumber("maxstartingtime");
+  if (el->FindElement("startern1"))
+    StarterN1 = el->FindElementValueAsNumber("startern1");
+  if (el->FindElement("ielumaxtorque"))
+    Ielu_max_torque = el->FindElementValueAsNumber("ielumaxtorque");
+  if (el->FindElement("itt_delay"))
+    ITT_Delay = el->FindElementValueAsNumber("itt_delay");
+
+  Element *table_element;
+  string name;
+  FGPropertyManager* PropertyManager = exec->GetPropertyManager();
+
+  while (true) {
+    table_element = el->FindNextElement("table");
+    if (!table_element) break;
+    name = table_element->GetAttributeValue("name");
+    if (name == "EnginePowerVC") {
+      EnginePowerVC = new FGTable(PropertyManager, table_element);
+    } else if (name == "EnginePowerRPM_N1") {
+      EnginePowerRPM_N1 = new FGTable(PropertyManager, table_element);
+    } else if (name == "ITT_N1") {
+      ITT_N1 = new FGTable(PropertyManager, table_element);
+    } else {
+      cerr << "Unknown table type: " << name << " in turbine definition." <<
+      endl;
+    }
+  }
+
+  // Pre-calculations and initializations
+
+  delay=1;
+  N1_factor = MaxN1 - IdleN1;
+  N2_factor = MaxN2 - IdleN2;
+  OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
+  if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0;  // just an estimate
+
+  cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n";
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// The main purpose of Calculate() is to determine what phase the engine should
+// be in, then call the corresponding function.
+
+double FGTurboProp::Calculate(void)
+{
+  TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
+  dt = State->Getdt() * Propulsion->GetRate();
+
+  ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
+
+  Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
+  if (Thruster->GetType() == FGThruster::ttPropeller) {
+    ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
+    ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
+    ((FGPropeller*)Thruster)->SetReverse(Reversed);
+    if (Reversed) {
+      ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd);
+    } else {
+      ((FGPropeller*)Thruster)->SetReverseCoef(0.0);
+    }
+  }
+
+  if (Reversed) {
+    if (ThrottleCmd < BetaRangeThrottleEnd) {
+        ThrottleCmd = 0.0;  // idle when in Beta-range
+    } else {
+      // when reversed:
+      ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
+    }
+  }
+
+  // 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;
+      Eng_ITT_degC = TAT;
+      Eng_Temperature = TAT;
+      OilTemp_degK = TAT+273.15;
+    }
+  }
+
+  if (!Running && Starter) {
+    if (phase == tpOff) {
+      phase = tpSpinUp;
+      if (StartTime < 0) StartTime=0;
+    }
+  }
+  if (!Running && !Cutoff && (N1 > 15.0)) {
+    phase = tpStart;
+    StartTime = -1;
+  }
+  if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
+  if (dt == 0) phase = tpTrim;
+  if (Starved) phase = tpOff;
+  if (Condition >= 10) {
+    phase = tpOff;
+    StartTime=-1;
+  }
+
+  if (Condition < 1) {
+    if (Ielu_max_torque > 0
+      && -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque()
+      && ThrottleCmd >= OldThrottle ) {
+      ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down
+      Ielu_intervent = true;
+    } else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) {
+      ThrottleCmd = OldThrottle;
+      ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up
+      Ielu_intervent = true;
+    } else {
+      Ielu_intervent = false;
+    }
+  } else {
+    Ielu_intervent = false;
+  }
+  OldThrottle = ThrottleCmd;
+
+  switch (phase) {
+    case tpOff:    Eng_HP = Off(); break;
+    case tpRun:    Eng_HP = Run(); break;
+    case tpSpinUp: Eng_HP = SpinUp(); break;
+    case tpStart:  Eng_HP = Start(); break;
+    default: Eng_HP = 0;
+  }
+
+  //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power);
+  return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired());
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurboProp::Off(void)
+{
+  double qbar = Auxiliary->Getqbar();
+  Running = false; EngStarting = false;
+
+  FuelFlow_pph = Seek(&FuelFlow_pph, 0, 800.0, 800.0);
+
+  //allow the air turn with generator
+  N1 = ExpSeek(&N1, qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5);
+
+  OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400);
+
+  Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400);
+  double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature);
+  Eng_ITT_degC  = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
+
+  OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
+
+  ConsumeFuel(); // for possible setting Starved = false when fuel tank
+                 // is refilled (fuel crossfeed etc.)
+
+  if (Prop_RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
+  return 0.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurboProp::Run(void)
+{
+  double idlethrust, milthrust, thrust, EngPower_HP, eff_coef;
+  Running = true; Starter = false; EngStarting = false;
+
+//---
+  double old_N1 = N1;
+  N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
+
+  EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+  EngPower_HP *= EnginePowerVC->GetValue();
+  if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
+
+  eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1
+  FuelFlow_pph = PSFC * EngPower_HP * eff_coef;
+
+  Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400);
+  double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1);
+  Eng_ITT_degC  = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
+
+  OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
+//---
+  EPR = 1.0 + thrust/MilThrust;
+
+  OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04);
+
+  ConsumeFuel();
+
+  if (Cutoff) phase = tpOff;
+  if (Starved) phase = tpOff;
+
+  return EngPower_HP;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurboProp::SpinUp(void)
+{
+  double EngPower_HP;
+  Running = false; EngStarting = true;
+  FuelFlow_pph = 0.0;
+
+  if (!GeneratorPower) {
+    EngStarting=false;
+    phase=tpOff;
+    StartTime = -1;
+    return 0.0;
+  }
+
+  N1 = ExpSeek(&N1, StarterN1, Idle_Max_Delay * 6, Idle_Max_Delay * 2.4);
+
+  Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400);
+  double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature);
+  Eng_ITT_degC  = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
+
+  OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400);
+
+  OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
+  NozzlePosition = 1.0;
+
+  EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+  EngPower_HP *= EnginePowerVC->GetValue();
+  if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
+
+  if (StartTime>=0) StartTime+=dt;
+  if (StartTime > MaxStartingTime && MaxStartingTime > 0) { //start failed due timeout
+    phase = tpOff;
+    StartTime = -1;
+  }
+
+  ConsumeFuel(); // for possible setting Starved = false when fuel tank
+                 // is refilled (fuel crossfeed etc.)
+
+  return EngPower_HP;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurboProp::Start(void)
+{
+  double EngPower_HP,eff_coef;
+  EngStarting = false;
+  if ((N1 > 15.0) && !Starved) {       // minimum 15% N2 needed for start
+    double old_N1 = N1;
+    Cranking = true;                   // provided for sound effects signal
+    if (N1 < IdleN1) {
+      EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+      EngPower_HP *= EnginePowerVC->GetValue();
+      if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
+      N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4);
+      eff_coef = 9.333 - (N1)/12; // 430%Fuel at 60%N1
+      FuelFlow_pph = PSFC * EngPower_HP * eff_coef;
+      Eng_Temperature = ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400);
+      double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1);
+      Eng_ITT_degC  = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
+
+      OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
+      OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04);
+
+    } else {
+      phase = tpRun;
+      Running = true;
+      Starter = false;
+      Cranking = false;
+      FuelFlow_pph = 0;
+      EngPower_HP=0.0;
+    }
+  } else {                 // no start if N2 < 15% or Starved
+    phase = tpOff;
+    Starter = false;
+  }
+
+  ConsumeFuel();
+
+  return EngPower_HP;
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurboProp::CalcFuelNeed(void)
+{
+  return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurboProp::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;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double decel_tau)
+{
+// exponential delay instead of the linear delay used in Seek
+  double v = *var;
+  if (v > target) {
+    v = (v - target) * exp ( -dt / decel_tau) + target;
+  } else if (v < target) {
+    v = (target - v) * (1 - exp ( -dt / accel_tau)) + v;
+  }
+  return v;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTurboProp::SetDefaults(void)
+{
+  Name = "Not defined";
+  N1 = N2 = 0.0;
+  Type = etTurboprop;
+  MilThrust = 10000.0;
+  IdleN1 = 30.0;
+  IdleN2 = 60.0;
+  MaxN1 = 100.0;
+  MaxN2 = 100.0;
+  ThrottleCmd = 0.0;
+  InletPosition = 1.0;
+  NozzlePosition = 1.0;
+  Reversed = false;
+  Cutoff = true;
+  phase = tpOff;
+  Stalled = false;
+  Seized = false;
+  Overtemp = false;
+  Fire = false;
+  Eng_ITT_degC = 0.0;
+
+  GeneratorPower=true;
+  Condition = 0;
+  Ielu_intervent=false;
+
+  Idle_Max_Delay = 1.0;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+string FGTurboProp::GetEngineLabels(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << Name << "_N1[" << EngineNumber << "]" << delimeter
+      << Name << "_N2[" << EngineNumber << "]" << delimeter
+      << Name << "__PwrAvailJVK[" << EngineNumber << "]" << delimeter
+      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGTurboProp::GetEngineValues(string delimeter)
+{
+  std::ostringstream buf;
+
+  buf << N1 << delimeter
+      << N2 << delimeter
+      << Thruster->GetThrusterValues(EngineNumber,delimeter);
+
+  return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTurboProp::bindmodel()
+{
+  char property_name[80];
+
+// ToDo: Do a proper Tie here, this should be read only.
+
+  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
+  PropertyManager->Tie( property_name, &N1);
+  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
+  PropertyManager->Tie( property_name, &N2);
+  snprintf(property_name, 80, "propulsion/engine[%u]/reverser", EngineNumber);
+  PropertyManager->Tie( property_name, &Reversed);
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTurboProp::unbind()
+{
+  char property_name[80];
+
+  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
+  PropertyManager->Untie(property_name);
+  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
+  PropertyManager->Untie(property_name);
+  snprintf(property_name, 80, "propulsion/engine[%u]/reverser", EngineNumber);
+  PropertyManager->Untie(property_name);
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGTurboProp::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 ****MUJ MOTOR TURBOPROP****\n";
+      cout << "\n    Engine Name: "         << Name << endl;
+      cout << "      MilThrust:   "         << MilThrust << endl;
+      cout << "      IdleN1:      "         << IdleN1 << endl;
+      cout << "      MaxN1:       "         << MaxN1 << endl;
+
+      cout << endl;
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGTurboProp" << endl;
+    if (from == 1) cout << "Destroyed:    FGTurboProp" << 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/models/propulsion/FGTurboProp.h b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h
new file mode 100755 (executable)
index 0000000..d1ac945
--- /dev/null
@@ -0,0 +1,204 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGTurboProp.h
+ Author:       Jiri "Javky" Javurek
+               based on SimTurbine and Turbine engine from David Culp
+ Date started: 05/14/2004
+
+ ------------- Copyright (C) 2004  (javky@email.cz)----------
+
+ 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
+--------------------------------------------------------------------------------
+05/14/2004  Created
+
+//JVK (mark)
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGTURBOPROP_H
+#define FGTURBOPROP_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <vector>
+#include "FGEngine.h"
+#include <input_output/FGXMLElement.h>
+#include <math/FGTable.h>
+
+#define ID_TURBOPROP "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Turboprop engine model.
+
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGTurboProp : public FGEngine
+{
+public:
+  /** Constructor
+      @param Executive pointer to executive structure
+      @param el pointer to the XML element representing the turbine engine
+      @param engine_number engine number*/
+  FGTurboProp(FGFDMExec* Executive, Element *el, int engine_number);
+  /// Destructor
+  ~FGTurboProp();
+
+  enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
+
+  double Calculate(void);
+  double CalcFuelNeed(void);
+
+  inline double GetPowerAvailable(void) const {return (Eng_HP * hptoftlbssec);}
+  inline double GetPowerAvailable_HP(void) const {return (Eng_HP);}
+  inline double GetPropRPM(void) const {return (Prop_RPM);}
+  inline double GetThrottleCmd(void) const {return (ThrottleCmd);}
+  inline bool GetIeluIntervent(void) const { return Ielu_intervent; }
+
+  double Seek(double* var, double target, double accel, double decel);
+  double ExpSeek(double* var, double target, double accel, double decel);
+
+  phaseType GetPhase(void) const { return phase; }
+
+  bool GetOvertemp(void) const {return Overtemp; }
+  bool GetFire(void) const { return Fire; }
+  bool GetReversed(void) const { return Reversed; }
+  bool GetCutoff(void) const { return Cutoff; }
+  int GetIgnition(void) const {return Ignition;}
+
+  double GetInlet(void) const { return InletPosition; }
+  double GetNozzle(void) const { return NozzlePosition; }
+  double GetN1(void) const {return N1;}
+  double GetN2(void) const {return N2;}
+  double GetEPR(void) const {return EPR;}
+  double GetITT(void) const {return Eng_ITT_degC;}
+  double GetEngStarting(void) const { return EngStarting; }
+
+  double getOilPressure_psi () const {return OilPressure_psi;}
+  double getOilTemp_degF (void) {return KelvinToFahrenheit(OilTemp_degK);}
+
+  inline bool GetGeneratorPower(void) const { return GeneratorPower; }
+  inline int GetCondition(void) const { return Condition; }
+
+  void SetIgnition(int ignition) {Ignition = ignition;}
+  void SetPhase( phaseType p ) { phase = p; }
+  void SetEPR(double epr) {EPR = epr;}
+  void SetReverse(bool reversed) { Reversed = reversed; }
+  void SetCutoff(bool cutoff) { Cutoff = cutoff; }
+
+  inline void SetGeneratorPower(bool gp) { GeneratorPower=gp; }
+  inline void SetCondition(bool c) { Condition=c; }
+
+  string GetEngineLabels(string delimeter);  // added from Turbine 0.9.6
+  string GetEngineValues(string delimeter);  // added from Turbine 0.9.6
+
+private:
+
+  phaseType phase;         ///< Operating mode, or "phase"
+  double MilThrust;        ///< Maximum Unaugmented Thrust, static @ S.L. (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 Reversed;
+  bool Cutoff;
+  int Ignition;
+
+  double EPR;
+  double OilPressure_psi;
+  double OilTemp_degK;
+  double InletPosition;
+  double NozzlePosition;
+
+  double Ielu_max_torque;      // max propeller torque (before ielu intervent)
+  bool Ielu_intervent;
+  double OldThrottle;
+
+  double BetaRangeThrottleEnd; // coef (0-1) where is end of beta-range
+  double ReverseMaxPower;      // coef (0-1) multiplies max throttle on reverse
+
+  double Idle_Max_Delay;       // time delay for exponencial
+  double MaxPower;             // max engine power [HP]
+  double StarterN1;               // rotates of generator maked by starter [%]
+  double MaxStartingTime;           // maximal time for start [s] (-1 means not used)
+  double Prop_RPM;             // propeller RPM
+  double Velocity;
+  double rho;
+  double PSFC;                 // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency
+
+  double Eng_HP;               // current engine power
+
+  double StartTime;               // engine strating time [s] (0 when start button pushed)
+
+  double  ITT_Delay;            // time delay for exponencial grow of ITT
+  double  Eng_ITT_degC;
+  double  Eng_Temperature;     // temperature inside engine
+
+  bool EngStarting;            // logicaly output - TRUE if engine is starting
+  bool GeneratorPower;
+  int Condition;
+
+  double Off(void);
+  double Run(void);
+  double SpinUp(void);
+  double Start(void);
+
+  void SetDefaults(void);
+  bool Load(FGFDMExec *exec, Element *el);
+  void bindmodel(void);
+  void unbind(void);
+  void Debug(int from);
+
+  FGTable* ITT_N1; // ITT temperature depending on throttle command
+  FGTable* EnginePowerRPM_N1;
+  FGTable* EnginePowerVC;
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
diff --git a/src/FDM/JSBSim/models/propulsion/Makefile.am b/src/FDM/JSBSim/models/propulsion/Makefile.am
new file mode 100644 (file)
index 0000000..5d2d72a
--- /dev/null
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libPropulsion.a
+
+libPropulsion_a_SOURCES = FGElectric.cpp FGEngine.cpp FGForce.cpp FGNozzle.cpp \
+                         FGPiston.cpp FGPropeller.cpp FGRocket.cpp FGRotor.cpp \
+                         FGTank.cpp FGThruster.cpp FGTurbine.cpp FGTurboProp.cpp
+
+noinst_HEADERS =  FGElectric.h FGEngine.h FGForce.h FGNozzle.h FGPiston.h \
+                  FGPropeller.h FGRocket.h FGRotor.h FGTank.h FGThruster.h \
+                  FGTurbine.h FGTurboProp.h
+
+INCLUDES = -I$(top_srcdir)/src/FDM/JSBSim
index d1c884fb236b15ba77b062a2a9a0ee1267a3e5cb..4848372241c6155088acf7e2c880a4a45e57793e 100644 (file)
@@ -25,6 +25,16 @@ else
 GFX_CODE = fg_os.cxx fg_os.hxx
 endif
 
+JSBSIM_LIBS = \
+       $(top_builddir)/src/FDM/JSBSim/libJSBSim.a \
+        $(top_builddir)/src/FDM/JSBSim/initialization/libInit.a \
+        $(top_builddir)/src/FDM/JSBSim/models/libModels.a \
+        $(top_builddir)/src/FDM/JSBSim/models/flight_control/libFlightControl.a\
+        $(top_builddir)/src/FDM/JSBSim/models/atmosphere/libAtmosphere.a \
+        $(top_builddir)/src/FDM/JSBSim/models/propulsion/libPropulsion.a \
+        $(top_builddir)/src/FDM/JSBSim/input_output/libInputOutput.a \
+        $(top_builddir)/src/FDM/JSBSim/math/libMath.a
+
 AM_CXXFLAGS = -DPKGLIBDIR=\"$(pkgdatadir)\"
 
 bin_PROGRAMS = fgfs metar
@@ -63,7 +73,7 @@ fgfs_LDADD = \
        $(top_builddir)/src/FDM/Balloon/libBalloon.a \
        $(top_builddir)/src/FDM/ExternalNet/libExternalNet.a \
        $(top_builddir)/src/FDM/ExternalPipe/libExternalPipe.a \
-       $(top_builddir)/src/FDM/JSBSim/libJSBSim.a \
+       $(JSBSIM_LIBS) \
        $(top_builddir)/src/FDM/YASim/libYASim.a \
        $(top_builddir)/src/FDM/JSBSim/filtersjb/libfiltersjb.a \
        $(top_builddir)/src/FDM/LaRCsim/libLaRCsim.a \
@@ -105,4 +115,4 @@ metar_LDADD = \
         -lplibnet -lplibul $(network_LIBS) \
         -lz $(base_LIBS)
 
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/FDM/JSBSim