]> git.mxchange.org Git - flightgear.git/commitdiff
Fix an issue where math.h doesn't define sqrt in namespace std (at least on MSVC...
authorehofman <ehofman>
Mon, 15 Mar 2004 09:24:57 +0000 (09:24 +0000)
committerehofman <ehofman>
Mon, 15 Mar 2004 09:24:57 +0000 (09:24 +0000)
src/FDM/JSBSim/FGColumnVector3.cpp
src/FDM/JSBSim/FGColumnVector3.h
src/FDM/JSBSim/FGColumnVector4.h
src/FDM/JSBSim/FGForce.cpp
src/FDM/JSBSim/FGJSBBase.cpp
src/FDM/JSBSim/FGLGear.cpp
src/FDM/JSBSim/FGMatrix33.cpp
src/FDM/JSBSim/FGOutput.cpp
src/FDM/JSBSim/FGPosition.cpp
src/FDM/JSBSim/filtersjb/FGCondition.cpp
src/FDM/JSBSim/filtersjb/FGSwitch.cpp

index 0e9c1060eafd0d6f63c4a1b766053edc78d914af..96a69e64b2dcb9e032f3a3e82df633eb15c27ae9 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-Module: FGColumnVector3.cpp\r
-Author: Originally by Tony Peden [formatted here (and broken??) by JSB]\r
-Date started: 1998\r
-Purpose: FGColumnVector3 class\r
-Called by: Various\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-??/??/??   TP   Created\r
-03/16/2000 JSB  Added exception throwing\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGColumnVector3.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_COLUMNVECTOR3;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-FGColumnVector3::FGColumnVector3(void)\r
-{\r
-  data[0] = data[1] = data[2] = 0.0;\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGColumnVector3 FGColumnVector3::operator/(const double scalar) const\r
-{\r
-  if (scalar != 0.0)\r
-    return operator*( 1.0/scalar );\r
-\r
-  cerr << "Attempt to divide by zero in method "\r
-    "FGColumnVector3::operator/(const double scalar), "\r
-    "object " << this << endl; \r
-  return FGColumnVector3();\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGColumnVector3& FGColumnVector3::operator/=(const double scalar)\r
-{\r
-  if (scalar != 0.0)\r
-    operator*=( 1.0/scalar );\r
-  else\r
-    cerr << "Attempt to divide by zero in method "\r
-      "FGColumnVector3::operator/=(const double scalar), "\r
-      "object " << this << endl;\r
-\r
-  return *this;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-double FGColumnVector3::Magnitude(void) const\r
-{\r
-  if (data[1] == 0.0 && data[2] == 0.0 && data[3] == 0.0)\r
-    return 0.0;\r
-  else\r
-    return sqrt( Entry(1)*Entry(1) +  Entry(2)*Entry(2) +  Entry(3)*Entry(3) );\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGColumnVector3& FGColumnVector3::Normalize(void)\r
-{\r
-  double Mag = Magnitude();\r
-\r
-  if (Mag != 0.0)\r
-    operator*=( 1.0/Mag );\r
-\r
-  return *this;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGColumnVector3 FGColumnVector3::multElementWise(const FGColumnVector3& V) const\r
-{\r
-  return FGColumnVector3(Entry(1) * V(1), Entry(2) * V(2), Entry(3) * V(3));\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-ostream& operator<<(ostream& os, const FGColumnVector3& col)\r
-{\r
-  os << col(1) << " , " << col(2) << " , " << col(3);\r
-  return os;\r
-}  \r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGColumnVector3::Debug(int from)\r
-{\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGColumnVector3" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGColumnVector3" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-\r
-} // namespace JSBSim\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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"
+
+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);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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 " << this << 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 " << this << endl;
+
+  return *this;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGColumnVector3::Magnitude(void) const
+{
+  if (data[1] == 0.0 && data[2] == 0.0 && data[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));
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ostream& operator<<(ostream& os, const FGColumnVector3& col)
+{
+  os << col(1) << " , " << col(2) << " , " << col(3);
+  return os;
+}  
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+//    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
index f5044709afb1a929f679cb629d19ececb2d37a90..b0a471dc2b927dd77c68b1bb8e39c362447d91b1 100644 (file)
@@ -33,7 +33,7 @@ INCLUDES
    SG_USING_STD(cerr);
    SG_USING_STD(cout);
    SG_USING_STD(endl);
-   SG_USING_STD(sqrt);
+//   SG_USING_STD(sqrt);
 #else
 #  include <string>
 #  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
index 1549453792623c7b370dddcade47f8f3623ebfc1..8b87c4841a49b0e3c309d45ee041366b236914a1 100644 (file)
@@ -31,7 +31,7 @@ INCLUDES
    SG_USING_STD(cerr);
    SG_USING_STD(cout);
    SG_USING_STD(endl);
-   SG_USING_STD(sqrt);
+//   SG_USING_STD(sqrt);
 #else
 #  include <string>
 #  if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
index d134b325fcee389102d8727aabeab4feead5733e..72256d198a91e605bfadb735412ffcbf1c99cc17 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Source:       FGForce.cpp\r
- Author:       Tony Peden\r
- Date started: 6/10/00\r
-\r
- ------------- Copyright (C) 1999  Anthony K. Peden (apeden@earthlink.net) -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-\r
- HISTORY\r
---------------------------------------------------------------------------------\r
-6/10/00  TP   Created\r
-\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-\r
-The purpose of this class is to provide storage for computed forces and\r
-encapsulate all the functionality associated with transforming those\r
-forces from their native coord system to the body system.  This includes\r
-computing the moments due to the difference between the point of application\r
-and the cg.\r
-\r
-*/\r
-\r
-#include "FGFDMExec.h"\r
-#include "FGAircraft.h"\r
-#include "FGTranslation.h"\r
-#include "FGMassBalance.h"\r
-#include "FGState.h"\r
-#include "FGForce.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_FORCE;\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGForce::FGForce(FGFDMExec *FDMExec) :\r
-                 ttype(tNone),\r
-                 fdmex(FDMExec)\r
-{\r
-  mT(1,1) = 1; //identity matrix\r
-  mT(2,2) = 1;\r
-  mT(3,3) = 1;\r
-  vSense.InitMatrix(1);\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGForce::~FGForce()\r
-{\r
-  Debug(1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGColumnVector3& FGForce::GetBodyForces(void)\r
-{\r
-  vFb = Transform()*(vFn.multElementWise(vSense));\r
-\r
-  // Find the distance from this vector's acting location to the cg; this\r
-  // needs to be done like this to convert from structural to body coords.\r
-  // CG and RP values are in inches\r
-\r
-  vDXYZ = fdmex->GetMassBalance()->StructuralToBody(vActingXYZn);\r
-\r
-  vM = vMn + vDXYZ*vFb;\r
-\r
-  return vFb;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33 FGForce::Transform(void)\r
-{\r
-  switch(ttype) {\r
-  case tWindBody:\r
-    return fdmex->GetState()->GetTs2b();\r
-  case tLocalBody:\r
-    return fdmex->GetState()->GetTl2b();\r
-  case tCustom:\r
-  case tNone:\r
-    return mT;\r
-  default:\r
-    cout << "Unrecognized tranform requested from FGForce::Transform()" << endl;\r
-    exit(1);\r
-  }\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGForce::SetAnglesToBody(double broll, double bpitch, double byaw)\r
-{\r
-  if (ttype == tCustom) {\r
-    double cp,sp,cr,sr,cy,sy;\r
-\r
-    cp=cos(bpitch); sp=sin(bpitch);\r
-    cr=cos(broll);  sr=sin(broll);\r
-    cy=cos(byaw);   sy=sin(byaw);\r
-\r
-    mT(1,1)=cp*cy;\r
-    mT(1,2)=cp*sy;\r
-    mT(1,3)=-1*sp;\r
-\r
-    mT(2,1)=sr*sp*cy-cr*sy;\r
-    mT(2,2)=sr*sp*sy+cr*cy;\r
-    mT(2,3)=sr*cp;\r
-\r
-    mT(3,1)=cr*sp*cy+sr*sy;\r
-    mT(3,2)=cr*sp*sy-sr*cy;\r
-    mT(3,3)=cr*cp;\r
-  }\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGForce::Debug(int from)\r
-{\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-    if (from == 0) { // Constructor\r
-\r
-    }\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGForce" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGForce" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-}\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 "FGAircraft.h"
+#include "FGTranslation.h"
+#include "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->GetState()->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;
+
+    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;
+    }
+  }
+}
+}
index f3188b54e99633007c9d8bf8aecd9dc4cf1e33f5..4ed156854ff6eb019f019ba4c432363eb2b0ae8e 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Module:       FGJSBBase.cpp\r
- Author:       Jon S. Berndt\r
- Date started: 07/01/01\r
- Purpose:      Encapsulates the JSBBase object\r
-\r
- ------------- Copyright (C) 2001  Jon S. Berndt (jsb@hal-pc.org) -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-07/01/01  JSB  Created\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGJSBBase.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_JSBBASE;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-char FGJSBBase::highint[5]  = {27, '[', '1', 'm', '\0'      };\r
-char FGJSBBase::halfint[5]  = {27, '[', '2', 'm', '\0'      };\r
-char FGJSBBase::normint[6]  = {27, '[', '2', '2', 'm', '\0' };\r
-char FGJSBBase::reset[5]    = {27, '[', '0', 'm', '\0'      };\r
-char FGJSBBase::underon[5]  = {27, '[', '4', 'm', '\0'      };\r
-char FGJSBBase::underoff[6] = {27, '[', '2', '4', 'm', '\0' };\r
-char FGJSBBase::fgblue[6]   = {27, '[', '3', '4', 'm', '\0' };\r
-char FGJSBBase::fgcyan[6]   = {27, '[', '3', '6', 'm', '\0' };\r
-char FGJSBBase::fgred[6]    = {27, '[', '3', '1', 'm', '\0' };\r
-char FGJSBBase::fggreen[6]  = {27, '[', '3', '2', 'm', '\0' };\r
-char FGJSBBase::fgdef[6]    = {27, '[', '3', '9', 'm', '\0' };\r
-\r
-const double FGJSBBase::radtodeg = 57.29578;\r
-const double FGJSBBase::degtorad = 1.745329E-2;\r
-const double FGJSBBase::hptoftlbssec = 550.0;\r
-const double FGJSBBase::psftoinhg = 0.014138;\r
-const double FGJSBBase::fpstokts = 0.592484;\r
-const double FGJSBBase::ktstofps = 1.68781;\r
-const double FGJSBBase::inchtoft = 0.08333333;\r
-const double FGJSBBase::in3tom3 = 1.638706E-5;\r
-double FGJSBBase::Reng = 1716.0;\r
-const double FGJSBBase::SHRatio = 1.40;\r
-\r
-// Note that definition of lbtoslug by the inverse of slugtolb and not\r
-// to a different constant you can also get from some tables will make\r
-// lbtoslug*slugtolb == 1 up to the magnitude of roundoff. So converting from\r
-// slug to lb and back will yield to the original value you started with up\r
-// to the magnitude of roundoff.\r
-// Taken from units gnu commandline tool\r
-const double FGJSBBase::slugtolb = 32.174049;\r
-const double FGJSBBase::lbtoslug = 1.0/slugtolb;\r
-\r
-const string FGJSBBase::needed_cfg_version = "1.61";\r
-const string FGJSBBase::JSBSim_version = "0.9.5";\r
-\r
-std::queue <FGJSBBase::Message*> FGJSBBase::Messages;\r
-FGJSBBase::Message FGJSBBase::localMsg;\r
-unsigned int FGJSBBase::messageId = 0;\r
-unsigned int FGJSBBase::frame = 0;\r
-\r
-short FGJSBBase::debug_lvl  = 1;\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::FGJSBBase()\r
-{\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::Message* FGJSBBase::PutMessage(Message* msg)\r
-{\r
-  Messages.push(msg);\r
-  return msg;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::Message* FGJSBBase::PutMessage(string text)\r
-{\r
-  Message *msg = new Message();\r
-  msg->text = text;\r
-  msg->messageId = messageId++;\r
-  msg->subsystem = "FDM";\r
-  msg->type = Message::eText;\r
-  Messages.push(msg);\r
-  return msg;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::Message* FGJSBBase::PutMessage(string text, bool bVal)\r
-{\r
-  Message *msg = new Message();\r
-  msg->text = text;\r
-  msg->messageId = messageId++;\r
-  msg->subsystem = "FDM";\r
-  msg->type = Message::eBool;\r
-  msg->bVal = bVal;\r
-  Messages.push(msg);\r
-  return msg;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::Message* FGJSBBase::PutMessage(string text, int iVal)\r
-{\r
-  Message *msg = new Message();\r
-  msg->text = text;\r
-  msg->messageId = messageId++;\r
-  msg->subsystem = "FDM";\r
-  msg->type = Message::eInteger;\r
-  msg->bVal = (iVal != 0);\r
-  Messages.push(msg);\r
-  return msg;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::Message* FGJSBBase::PutMessage(string text, double dVal)\r
-{\r
-  Message *msg = new Message();\r
-  msg->text = text;\r
-  msg->messageId = messageId++;\r
-  msg->subsystem = "FDM";\r
-  msg->type = Message::eDouble;\r
-  msg->bVal = (dVal != 0.0);\r
-  Messages.push(msg);\r
-  return msg;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::Message* FGJSBBase::ReadMessage(void)\r
-{\r
-  if (!Messages.empty()) return Messages.front();\r
-  else                   return NULL;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGJSBBase::Message* FGJSBBase::ProcessMessage(void)\r
-{\r
-  if (!Messages.empty())\r
-    localMsg = *(Messages.front());\r
-  else\r
-    return NULL;\r
-  Messages.pop();\r
-  return &localMsg;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGJSBBase::disableHighLighting(void) {\r
-  highint[0]='\0';\r
-  halfint[0]='\0';\r
-  normint[0]='\0';\r
-  reset[0]='\0';\r
-  underon[0]='\0';\r
-  underoff[0]='\0';\r
-  fgblue[0]='\0';\r
-  fgcyan[0]='\0';\r
-  fgred[0]='\0';\r
-  fggreen[0]='\0';\r
-  fgdef[0]='\0';\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-} // namespace JSBSim\r
-\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGJSBBase.cpp
+ Author:       Jon S. Berndt
+ Date started: 07/01/01
+ Purpose:      Encapsulates the JSBBase object
+
+ ------------- 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
+--------------------------------------------------------------------------------
+
+HISTORY
+--------------------------------------------------------------------------------
+07/01/01  JSB  Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGJSBBase.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_JSBBASE;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+char FGJSBBase::highint[5]  = {27, '[', '1', 'm', '\0'      };
+char FGJSBBase::halfint[5]  = {27, '[', '2', 'm', '\0'      };
+char FGJSBBase::normint[6]  = {27, '[', '2', '2', 'm', '\0' };
+char FGJSBBase::reset[5]    = {27, '[', '0', 'm', '\0'      };
+char FGJSBBase::underon[5]  = {27, '[', '4', 'm', '\0'      };
+char FGJSBBase::underoff[6] = {27, '[', '2', '4', 'm', '\0' };
+char FGJSBBase::fgblue[6]   = {27, '[', '3', '4', 'm', '\0' };
+char FGJSBBase::fgcyan[6]   = {27, '[', '3', '6', 'm', '\0' };
+char FGJSBBase::fgred[6]    = {27, '[', '3', '1', 'm', '\0' };
+char FGJSBBase::fggreen[6]  = {27, '[', '3', '2', 'm', '\0' };
+char FGJSBBase::fgdef[6]    = {27, '[', '3', '9', 'm', '\0' };
+
+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::fpstokts = 0.592484;
+const double FGJSBBase::ktstofps = 1.68781;
+const double FGJSBBase::inchtoft = 0.08333333;
+const double FGJSBBase::in3tom3 = 1.638706E-5;
+double FGJSBBase::Reng = 1716.0;
+const double FGJSBBase::SHRatio = 1.40;
+
+// Note that definition of lbtoslug by the inverse of slugtolb and not
+// to a different constant you can also get from some tables will make
+// lbtoslug*slugtolb == 1 up to the magnitude of roundoff. So converting from
+// slug to lb and back will yield to the original value you started with up
+// to the magnitude of roundoff.
+// Taken from units gnu commandline tool
+const double FGJSBBase::slugtolb = 32.174049;
+const double FGJSBBase::lbtoslug = 1.0/slugtolb;
+
+const string FGJSBBase::needed_cfg_version = "1.61";
+const string FGJSBBase::JSBSim_version = "0.9.5";
+
+std::queue <FGJSBBase::Message*> FGJSBBase::Messages;
+FGJSBBase::Message FGJSBBase::localMsg;
+unsigned int FGJSBBase::messageId = 0;
+unsigned int FGJSBBase::frame = 0;
+
+short FGJSBBase::debug_lvl  = 1;
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::FGJSBBase()
+{
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::PutMessage(Message* msg)
+{
+  Messages.push(msg);
+  return msg;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::PutMessage(string text)
+{
+  Message *msg = new Message();
+  msg->text = text;
+  msg->messageId = messageId++;
+  msg->subsystem = "FDM";
+  msg->type = Message::eText;
+  Messages.push(msg);
+  return msg;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::PutMessage(string text, bool bVal)
+{
+  Message *msg = new Message();
+  msg->text = text;
+  msg->messageId = messageId++;
+  msg->subsystem = "FDM";
+  msg->type = Message::eBool;
+  msg->bVal = bVal;
+  Messages.push(msg);
+  return msg;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::PutMessage(string text, int iVal)
+{
+  Message *msg = new Message();
+  msg->text = text;
+  msg->messageId = messageId++;
+  msg->subsystem = "FDM";
+  msg->type = Message::eInteger;
+  msg->bVal = (iVal != 0);
+  Messages.push(msg);
+  return msg;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::PutMessage(string text, double dVal)
+{
+  Message *msg = new Message();
+  msg->text = text;
+  msg->messageId = messageId++;
+  msg->subsystem = "FDM";
+  msg->type = Message::eDouble;
+  msg->bVal = (dVal != 0.0);
+  Messages.push(msg);
+  return msg;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::ReadMessage(void)
+{
+  if (!Messages.empty()) return Messages.front();
+  else                   return NULL;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGJSBBase::Message* FGJSBBase::ProcessMessage(void)
+{
+  if (!Messages.empty())
+    localMsg = *(Messages.front());
+  else
+    return NULL;
+  Messages.pop();
+  return &localMsg;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGJSBBase::disableHighLighting(void) {
+  highint[0]='\0';
+  halfint[0]='\0';
+  normint[0]='\0';
+  reset[0]='\0';
+  underon[0]='\0';
+  underoff[0]='\0';
+  fgblue[0]='\0';
+  fgcyan[0]='\0';
+  fgred[0]='\0';
+  fggreen[0]='\0';
+  fgdef[0]='\0';
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+} // namespace JSBSim
+
index c9c41835065a41b4ff032b315aa561e43da8d98d..276ec70d8af78205d12a454aa5ea3e61463fd784 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Module:       FGLGear.cpp\r
- Author:       Jon S. Berndt\r
-               Norman H. Princen\r
- Date started: 11/18/99\r
- Purpose:      Encapsulates the landing gear elements\r
- Called by:    FGAircraft\r
-\r
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-11/18/99   JSB   Created\r
-01/30/01   NHP   Extended gear model to properly simulate steering and braking\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGLGear.h"\r
-\r
-namespace JSBSim {\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-DEFINITIONS\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-GLOBAL DATA\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_LGEAR;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)\r
-{\r
-  string tmp;\r
-  \r
-  *AC_cfg >> tmp >> name >> vXYZ(1) >> vXYZ(2) >> vXYZ(3)\r
-            >> kSpring >> bDamp>> dynamicFCoeff >> staticFCoeff\r
-                  >> rollingFCoeff >> sSteerType >> sBrakeGroup \r
-                     >> maxSteerAngle >> sRetractable;\r
-\r
-  if      (sBrakeGroup == "LEFT"  ) eBrakeGrp = bgLeft;\r
-  else if (sBrakeGroup == "RIGHT" ) eBrakeGrp = bgRight;\r
-  else if (sBrakeGroup == "CENTER") eBrakeGrp = bgCenter;\r
-  else if (sBrakeGroup == "NOSE"  ) eBrakeGrp = bgNose;\r
-  else if (sBrakeGroup == "TAIL"  ) eBrakeGrp = bgTail;\r
-  else if (sBrakeGroup == "NONE"  ) eBrakeGrp = bgNone;\r
-  else {\r
-    cerr << "Improper braking group specification in config file: "\r
-         << sBrakeGroup << " is undefined." << endl;\r
-  }\r
-\r
-  if      (sSteerType == "STEERABLE") eSteerType = stSteer;\r
-  else if (sSteerType == "FIXED"    ) eSteerType = stFixed;\r
-  else if (sSteerType == "CASTERED" ) eSteerType = stCaster;\r
-  else {\r
-    cerr << "Improper steering type specification in config file: "\r
-         << sSteerType << " is undefined." << endl;\r
-  }\r
-  \r
-  if ( sRetractable == "RETRACT" ) {\r
-    isRetractable = true;\r
-  } else  {\r
-    isRetractable = false;\r
-  }  \r
-  \r
-  GearUp = false;\r
-  GearDown = true;\r
-  Servicable = true;\r
-\r
-// Add some AI here to determine if gear is located properly according to its\r
-// brake group type ??\r
-\r
-  State       = Exec->GetState();\r
-  Aircraft    = Exec->GetAircraft();\r
-  Position    = Exec->GetPosition();\r
-  Rotation    = Exec->GetRotation();\r
-  FCS         = Exec->GetFCS();\r
-  MassBalance = Exec->GetMassBalance();\r
-\r
-  WOW = lastWOW = true; // should the value be initialized to true?\r
-  ReportEnable = true;\r
-  FirstContact = false;\r
-  StartedGroundRun = false;\r
-  TakeoffReported = LandingReported = false;\r
-  LandingDistanceTraveled = TakeoffDistanceTraveled = TakeoffDistanceTraveled50ft = 0.0;\r
-  MaximumStrutForce = MaximumStrutTravel = 0.0;\r
-  SideForce = RollingForce = 0.0;\r
-  SinkRate = GroundSpeed = 0.0;\r
-\r
-  vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);\r
-  \r
-  vLocalGear = State->GetTb2l() * vWhlBodyVec;\r
-\r
-  compressLength  = 0.0;\r
-  compressSpeed   = 0.0;\r
-  brakePct        = 0.0;\r
-  maxCompLen      = 0.0;\r
-\r
-  WheelSlip = lastWheelSlip = 0.0;\r
-\r
-  compressLength  = 0.0;\r
-  compressSpeed   = 0.0;\r
-  brakePct        = 0.0;\r
-  maxCompLen      = 0.0;\r
-\r
-  TirePressureNorm = 1.0;\r
-\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGLGear::FGLGear(const FGLGear& lgear)\r
-{\r
-  State    = lgear.State;\r
-  Aircraft = lgear.Aircraft;\r
-  Position = lgear.Position;\r
-  Rotation = lgear.Rotation;\r
-  Exec     = lgear.Exec;\r
-  FCS      = lgear.FCS;\r
-  MassBalance = lgear.MassBalance;\r
-\r
-  vXYZ = lgear.vXYZ;\r
-  vMoment = lgear.vMoment;\r
-  vWhlBodyVec = lgear.vWhlBodyVec;\r
-  vLocalGear = lgear.vLocalGear;\r
-\r
-  WOW                = lgear.WOW;\r
-  lastWOW            = lgear.lastWOW;\r
-  ReportEnable       = lgear.ReportEnable;\r
-  FirstContact       = lgear.FirstContact;\r
-  StartedGroundRun   = lgear.StartedGroundRun;\r
-  LandingDistanceTraveled   = lgear.LandingDistanceTraveled;\r
-  TakeoffDistanceTraveled   = lgear.TakeoffDistanceTraveled;\r
-  TakeoffDistanceTraveled50ft   = lgear.TakeoffDistanceTraveled50ft;\r
-  MaximumStrutForce  = lgear.MaximumStrutForce;\r
-  MaximumStrutTravel = lgear.MaximumStrutTravel;\r
-  SideForce          = lgear.SideForce;\r
-  RollingForce       = lgear.RollingForce;\r
-\r
-  kSpring         = lgear.kSpring;\r
-  bDamp           = lgear.bDamp;\r
-  compressLength  = lgear.compressLength;\r
-  compressSpeed   = lgear.compressSpeed;\r
-  staticFCoeff    = lgear.staticFCoeff;\r
-  dynamicFCoeff   = lgear.dynamicFCoeff;\r
-  rollingFCoeff   = lgear.rollingFCoeff;\r
-  brakePct        = lgear.brakePct;\r
-  maxCompLen      = lgear.maxCompLen;\r
-  SinkRate        = lgear.SinkRate;\r
-  GroundSpeed     = lgear.GroundSpeed;\r
-  LandingReported = lgear.LandingReported;\r
-  TakeoffReported = lgear.TakeoffReported;\r
-  name            = lgear.name;\r
-  sSteerType      = lgear.sSteerType;\r
-  sRetractable    = lgear.sRetractable;\r
-  eSteerType      = lgear.eSteerType;\r
-  sBrakeGroup     = lgear.sBrakeGroup;\r
-  eBrakeGrp       = lgear.eBrakeGrp;\r
-  maxSteerAngle   = lgear.maxSteerAngle;\r
-  isRetractable   = lgear.isRetractable;\r
-  GearUp          = lgear.GearUp;\r
-  GearDown        = lgear.GearDown;\r
-  WheelSlip       = lgear.WheelSlip;\r
-  lastWheelSlip   = lgear.lastWheelSlip;\r
-  TirePressureNorm = lgear.TirePressureNorm;\r
-  Servicable      = lgear.Servicable;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGLGear::~FGLGear()\r
-{\r
-  Debug(1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGColumnVector3& FGLGear::Force(void)\r
-{\r
-  double SteerGain = 0;\r
-  double SinWheel, CosWheel;\r
-  double deltaSlip;\r
-  double deltaT = State->Getdt()*Aircraft->GetRate();\r
-\r
-  vForce.InitMatrix();\r
-  vMoment.InitMatrix();\r
-\r
-  if (isRetractable) {\r
-    if (FCS->GetGearPos() < 0.01) {\r
-      GearUp   = true;\r
-      GearDown = false;\r
-     } else if (FCS->GetGearPos() > 0.99) {\r
-      GearDown = true;\r
-      GearUp   = false;\r
-     } else {\r
-      GearUp   = false;\r
-      GearDown = false;\r
-     }\r
-  } else {\r
-      GearUp   = false;\r
-      GearDown = true;\r
-  }         \r
-      \r
-  if (GearDown) {\r
-\r
-    vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);\r
-\r
-// vWhlBodyVec now stores the vector from the cg to this wheel\r
-\r
-    vLocalGear = State->GetTb2l() * vWhlBodyVec;\r
-\r
-// vLocalGear now stores the vector from the cg to the wheel in local coords.\r
-\r
-    compressLength = vLocalGear(eZ) - Position->GetDistanceAGL();\r
-\r
-// The compression length is currently measured in the Z-axis, only, at this time.\r
-// It should be measured along the strut axis. If the local-frame gear position\r
-// "hangs down" below the CG greater than the altitude, then the compressLength\r
-// will be positive - i.e. the gear will have made contact.\r
-\r
-    if (compressLength > 0.00) {\r
-\r
-      WOW = true; // Weight-On-Wheels is true\r
-\r
-// The next equation should really use the vector to the contact patch of the tire\r
-// including the strut compression and not vWhlBodyVec.  Will fix this later.\r
-// As it stands, now, the following equation takes the aircraft body-frame\r
-// rotational rate and calculates the cross-product with the vector from the CG\r
-// to the wheel, thus producing the instantaneous velocity vector of the tire\r
-// in Body coords. The frame is also converted to local coordinates. When the\r
-// aircraft local-frame velocity is added to this quantity, the total velocity of\r
-// the wheel in local frame is then known. Subsequently, the compression speed\r
-// (used for calculating damping force) is found by taking the Z-component of the\r
-// wheel velocity.\r
-\r
-      vWhlVelVec      =  State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);\r
-      vWhlVelVec     +=  Position->GetVel();\r
-      compressSpeed   =  vWhlVelVec(eZ);\r
-\r
-// If this is the first time the wheel has made contact, remember some values\r
-// for later printout.\r
-\r
-      if (!FirstContact) {\r
-        FirstContact  = true;\r
-        SinkRate      =  compressSpeed;\r
-        GroundSpeed   =  Position->GetVel().Magnitude();\r
-        TakeoffReported = false;\r
-      }\r
-\r
-// If the takeoff run is starting, initialize.\r
-\r
-      if ((Position->GetVel().Magnitude() > 0.1) &&\r
-          (FCS->GetBrake(bgLeft) == 0) &&\r
-          (FCS->GetBrake(bgRight) == 0) &&\r
-          (FCS->GetThrottlePos(0) == 1) && !StartedGroundRun)\r
-      {\r
-        TakeoffDistanceTraveled = 0;\r
-        TakeoffDistanceTraveled50ft = 0;\r
-        StartedGroundRun = true;\r
-      }\r
-\r
-// The following needs work regarding friction coefficients and braking and\r
-// steering The BrakeFCoeff formula assumes that an anti-skid system is used.\r
-// It also assumes that we won't be turning and braking at the same time.\r
-// Will fix this later.\r
-// [JSB] The braking force coefficients include normal rolling coefficient +\r
-// a percentage of the static friction coefficient based on braking applied.\r
-\r
-      switch (eBrakeGrp) {\r
-      case bgLeft:\r
-         BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +\r
-                        staticFCoeff*FCS->GetBrake(bgLeft) );\r
-        break;\r
-      case bgRight:\r
-        BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +\r
-                         staticFCoeff*FCS->GetBrake(bgRight) );\r
-        break;\r
-      case bgCenter:\r
-        BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +\r
-                         staticFCoeff*FCS->GetBrake(bgCenter) );\r
-        break;\r
-      case bgNose:\r
-        BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +\r
-                         staticFCoeff*FCS->GetBrake(bgCenter) );\r
-        break;\r
-      case bgTail:\r
-        BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +\r
-                         staticFCoeff*FCS->GetBrake(bgCenter) );\r
-        break;\r
-      case bgNone:\r
-        BrakeFCoeff =  rollingFCoeff;\r
-        break;\r
-      default:\r
-        cerr << "Improper brake group membership detected for this gear." << endl;\r
-        break;\r
-      }\r
-\r
-      switch (eSteerType) {\r
-      case stSteer:\r
-        SteerAngle = -maxSteerAngle * FCS->GetDrCmd() * 0.01745; \r
-        break;\r
-      case stFixed:\r
-        SteerAngle = 0.0;\r
-        break;\r
-      case stCaster:\r
-// Note to Jon: This is not correct for castering gear.  I'll fix it later.\r
-        SteerAngle = 0.0;\r
-        break;\r
-      default:\r
-        cerr << "Improper steering type membership detected for this gear." << endl;\r
-        break;\r
-      }\r
-\r
-// Transform the wheel velocities from the local axis system to the wheel axis system.\r
-// For now, steering angle is assumed to happen in the Local Z axis,\r
-// not the strut axis as it should be.  Will fix this later.\r
-\r
-      SinWheel      = sin(Rotation->Getpsi() + SteerAngle);\r
-      CosWheel      = cos(Rotation->Getpsi() + SteerAngle);\r
-      RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;\r
-      SideWhlVel    = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;\r
-\r
-// Calculate tire slip angle.\r
-\r
-      if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {\r
-        WheelSlip = 0.0;\r
-      } else if (fabs(RollingWhlVel) < 1.0) {\r
-        WheelSlip = 0.05*radtodeg*atan2(SideWhlVel, RollingWhlVel) + 0.95*WheelSlip;\r
-      } else {\r
-        WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);\r
-      }\r
-/*\r
-      double maxdeltaSlip = 0.5*deltaT;\r
-\r
-      if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {\r
-        WheelSlip = 0.0;\r
-      } else if (RollingWhlVel < 1.0) {\r
-        WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);\r
-        deltaSlip = WheelSlip - lastWheelSlip;\r
-        if (fabs(deltaSlip) > maxdeltaSlip) {\r
-          if (WheelSlip > lastWheelSlip) {\r
-            WheelSlip = lastWheelSlip + maxdeltaSlip;\r
-          } else if (WheelSlip < lastWheelSlip) {\r
-            WheelSlip = lastWheelSlip - maxdeltaSlip;\r
-          }\r
-        }\r
-      } else {\r
-        WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);\r
-      }\r
-\r
-      if ((WheelSlip < 0.0 && lastWheelSlip > 0.0) ||\r
-          (WheelSlip > 0.0 && lastWheelSlip < 0.0))\r
-      {\r
-        WheelSlip = 0.0;\r
-      }\r
-*/    \r
-      lastWheelSlip = WheelSlip;\r
-\r
-// Compute the sideforce coefficients using similar assumptions to LaRCSim for now.\r
-// Allow a maximum of 10 degrees tire slip angle before wheel slides.  At that point,\r
-// transition from static to dynamic friction.  There are more complicated formulations\r
-// of this that avoid the discrete jump.  Will fix this later.\r
-\r
-      if (fabs(WheelSlip) <= 20.0) {\r
-        FCoeff = staticFCoeff*WheelSlip/20.0;\r
-      } else if (fabs(WheelSlip) <= 40.0) {\r
-//        FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;\r
-        FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 20.0)/20.0 + \r
-                  staticFCoeff*(40.0 - fabs(WheelSlip))/20.0)*fabs(WheelSlip)/WheelSlip;\r
-      } else {\r
-        FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;\r
-      }\r
-\r
-// Compute the vertical force on the wheel using square-law damping (per comment\r
-// in paper AIAA-2000-4303 - see header prologue comments). We might consider\r
-// allowing for both square and linear damping force calculation. Also need to\r
-// possibly give a "rebound damping factor" that differs from the compression\r
-// case.\r
-\r
-      vLocalForce(eZ) =  min(-compressLength * kSpring\r
-                             - compressSpeed * bDamp, (double)0.0);\r
-\r
-      MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));\r
-      MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));\r
-\r
-// Compute the forces in the wheel ground plane.\r
-\r
-      RollingForce = 0;\r
-      if (fabs(RollingWhlVel) > 1E-3) {\r
-        RollingForce = (1.0 - TirePressureNorm) * 30\r
-                       + vLocalForce(eZ) * BrakeFCoeff\r
-                       * fabs(RollingWhlVel)/RollingWhlVel;\r
-      }\r
-      SideForce    = vLocalForce(eZ) * FCoeff;\r
-\r
-// Transform these forces back to the local reference frame.\r
-\r
-      vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel;\r
-      vLocalForce(eY) = SideForce*CosWheel    + RollingForce*SinWheel;\r
-\r
-// Note to Jon: At this point the forces will be too big when the airplane is\r
-// stopped or rolling to a stop.  We need to make sure that the gear forces just\r
-// balance out the non-gear forces when the airplane is stopped.  That way the\r
-// airplane won't start to accelerate until the non-gear/ forces are larger than\r
-// the gear forces.  I think that the proper fix should go into FGAircraft::FMGear.\r
-// This routine would only compute the local strut forces and return them to\r
-// FMGear. All of the gear forces would get adjusted in FMGear using the total\r
-// non-gear forces. Then the gear moments would be calculated. If strange things\r
-// start happening to the airplane during testing as it rolls to a stop, then we\r
-// need to implement this change.  I ran out of time to do it now but have the\r
-// equations.\r
-\r
-// Transform the forces back to the body frame and compute the moment.\r
-\r
-      vForce  = State->GetTl2b() * vLocalForce;\r
-      vMoment = vWhlBodyVec * vForce;\r
-\r
-    } else { // Gear is NOT compressed\r
-\r
-      WOW = false;\r
-\r
-      if (Position->GetDistanceAGL() > 200.0) {\r
-        FirstContact = false;\r
-        StartedGroundRun = false;\r
-        LandingReported = false;\r
-        LandingDistanceTraveled = 0.0;\r
-        MaximumStrutForce = MaximumStrutTravel = 0.0;\r
-      }\r
-\r
-      compressLength = 0.0; // reset compressLength to zero for data output validity\r
-    }\r
-\r
-    if (FirstContact) LandingDistanceTraveled += Position->GetVground()*deltaT;\r
-  \r
-    if (StartedGroundRun) {\r
-       TakeoffDistanceTraveled50ft += Position->GetVground()*deltaT;\r
-      if (WOW) TakeoffDistanceTraveled += Position->GetVground()*deltaT;\r
-    }\r
-\r
-    if (ReportEnable && Position->GetVground() <= 0.05 && !LandingReported) {\r
-      if (debug_lvl > 0) Report(erLand);\r
-    }\r
-\r
-    if (ReportEnable && !TakeoffReported &&\r
-       (vLocalGear(eZ) - Position->GetDistanceAGL()) < -50.0)\r
-    {\r
-      if (debug_lvl > 0) Report(erTakeoff);\r
-    }\r
-\r
-    if (lastWOW != WOW) {\r
-      PutMessage("GEAR_CONTACT: " + name, WOW);\r
-    }\r
-\r
-    lastWOW = WOW;\r
-\r
-// Crash detection logic (really out-of-bounds detection)\r
-\r
-    if (compressLength > 500.0 ||\r
-        vForce.Magnitude() > 100000000.0 ||\r
-        vMoment.Magnitude() > 5000000000.0 ||\r
-        SinkRate > 1.4666*30)\r
-    {\r
-      PutMessage("Crash Detected: Simulation FREEZE.");\r
-      Exec->Freeze();\r
-    }\r
-  } \r
-  return vForce; \r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGLGear::Report(ReportType repType)\r
-{\r
-  switch(repType) {\r
-  case erLand:\r
-    cout << endl << "Touchdown report for " << name << endl;\r
-    cout << "  Sink rate at contact:  " << SinkRate                << " fps,    "\r
-                                << SinkRate*0.3048          << " mps"     << endl;\r
-    cout << "  Contact ground speed:  " << GroundSpeed*.5925       << " knots,  "\r
-                                << GroundSpeed*0.3048       << " mps"     << endl;\r
-    cout << "  Maximum contact force: " << MaximumStrutForce       << " lbs,    "\r
-                                << MaximumStrutForce*4.448  << " Newtons" << endl;\r
-    cout << "  Maximum strut travel:  " << MaximumStrutTravel*12.0 << " inches, "\r
-                                << MaximumStrutTravel*30.48 << " cm"      << endl;\r
-    cout << "  Distance traveled:     " << LandingDistanceTraveled        << " ft,     "\r
-                                << LandingDistanceTraveled*0.3048  << " meters"  << endl;\r
-    LandingReported = true;\r
-    break;\r
-  case erTakeoff:\r
-    cout << endl << "Takeoff report for " << name << endl;\r
-    cout << "  Distance traveled:                " << TakeoffDistanceTraveled\r
-         << " ft,     " << TakeoffDistanceTraveled*0.3048  << " meters"  << endl;\r
-    cout << "  Distance traveled (over 50'):     " << TakeoffDistanceTraveled50ft\r
-         << " ft,     " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl;\r
-    TakeoffReported = true;\r
-    break;\r
-  }\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGLGear::Debug(int from)\r
-{\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-    if (from == 0) { // Constructor\r
-      cout << "    Name: "               << name          << endl;\r
-      cout << "      Location: "         << vXYZ          << endl;\r
-      cout << "      Spring Constant:  " << kSpring       << endl;\r
-      cout << "      Damping Constant: " << bDamp         << endl;\r
-      cout << "      Dynamic Friction: " << dynamicFCoeff << endl;\r
-      cout << "      Static Friction:  " << staticFCoeff  << endl;\r
-      cout << "      Rolling Friction: " << rollingFCoeff << endl;\r
-      cout << "      Steering Type:    " << sSteerType    << endl;\r
-      cout << "      Grouping:         " << sBrakeGroup   << endl;\r
-      cout << "      Max Steer Angle:  " << maxSteerAngle << endl;\r
-      cout << "      Retractable:      " << sRetractable  << endl;\r
-    }\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGLGear" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGLGear" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-\r
-} // namespace JSBSim\r
-\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
+{
+  string tmp;
+  
+  *AC_cfg >> tmp >> name >> vXYZ(1) >> vXYZ(2) >> vXYZ(3)
+            >> kSpring >> bDamp>> dynamicFCoeff >> staticFCoeff
+                  >> rollingFCoeff >> sSteerType >> sBrakeGroup 
+                     >> maxSteerAngle >> sRetractable;
+
+  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 {
+    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 {
+    cerr << "Improper steering type specification in config file: "
+         << sSteerType << " is undefined." << endl;
+  }
+  
+  if ( sRetractable == "RETRACT" ) {
+    isRetractable = true;
+  } else  {
+    isRetractable = false;
+  }  
+  
+  GearUp = false;
+  GearDown = true;
+  Servicable = true;
+
+// Add some AI here to determine if gear is located properly according to its
+// brake group type ??
+
+  State       = Exec->GetState();
+  Aircraft    = Exec->GetAircraft();
+  Position    = Exec->GetPosition();
+  Rotation    = Exec->GetRotation();
+  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 = State->GetTb2l() * vWhlBodyVec;
+
+  compressLength  = 0.0;
+  compressSpeed   = 0.0;
+  brakePct        = 0.0;
+  maxCompLen      = 0.0;
+
+  WheelSlip = lastWheelSlip = 0.0;
+
+  compressLength  = 0.0;
+  compressSpeed   = 0.0;
+  brakePct        = 0.0;
+  maxCompLen      = 0.0;
+
+  TirePressureNorm = 1.0;
+
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGLGear::FGLGear(const FGLGear& lgear)
+{
+  State    = lgear.State;
+  Aircraft = lgear.Aircraft;
+  Position = lgear.Position;
+  Rotation = lgear.Rotation;
+  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;
+  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;
+  eSteerType      = lgear.eSteerType;
+  sBrakeGroup     = lgear.sBrakeGroup;
+  eBrakeGrp       = lgear.eBrakeGrp;
+  maxSteerAngle   = lgear.maxSteerAngle;
+  isRetractable   = lgear.isRetractable;
+  GearUp          = lgear.GearUp;
+  GearDown        = lgear.GearDown;
+  WheelSlip       = lgear.WheelSlip;
+  lastWheelSlip   = lgear.lastWheelSlip;
+  TirePressureNorm = lgear.TirePressureNorm;
+  Servicable      = lgear.Servicable;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGLGear::~FGLGear()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGColumnVector3& FGLGear::Force(void)
+{
+  double SteerGain = 0;
+  double SinWheel, CosWheel;
+  double deltaSlip;
+  double deltaT = State->Getdt()*Aircraft->GetRate();
+
+  vForce.InitMatrix();
+  vMoment.InitMatrix();
+
+  if (isRetractable) {
+    if (FCS->GetGearPos() < 0.01) {
+      GearUp   = true;
+      GearDown = false;
+     } else if (FCS->GetGearPos() > 0.99) {
+      GearDown = true;
+      GearUp   = false;
+     } else {
+      GearUp   = false;
+      GearDown = false;
+     }
+  } else {
+      GearUp   = false;
+      GearDown = true;
+  }         
+      
+  if (GearDown) {
+
+    vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);
+
+// vWhlBodyVec now stores the vector from the cg to this wheel
+
+    vLocalGear = State->GetTb2l() * vWhlBodyVec;
+
+// vLocalGear now stores the vector from the cg to the wheel in local coords.
+
+    compressLength = vLocalGear(eZ) - Position->GetDistanceAGL();
+
+// The compression length is currently measured in the Z-axis, only, at this time.
+// It should be measured along the strut axis. If the local-frame gear position
+// "hangs down" below the CG greater than the altitude, then the compressLength
+// will be positive - i.e. the gear will have made contact.
+
+    if (compressLength > 0.00) {
+
+      WOW = true; // Weight-On-Wheels is true
+
+// The next equation should really use the vector to the contact patch of the tire
+// including the strut compression and not vWhlBodyVec.  Will fix this later.
+// As it stands, now, the following equation takes the aircraft body-frame
+// rotational rate and calculates the cross-product with the vector from the CG
+// to the wheel, thus producing the instantaneous velocity vector of the tire
+// in Body coords. The frame is also converted to local coordinates. When the
+// aircraft local-frame velocity is added to this quantity, the total velocity of
+// the wheel in local frame is then known. Subsequently, the compression speed
+// (used for calculating damping force) is found by taking the Z-component of the
+// wheel velocity.
+
+      vWhlVelVec      =  State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);
+      vWhlVelVec     +=  Position->GetVel();
+      compressSpeed   =  vWhlVelVec(eZ);
+
+// If this is the first time the wheel has made contact, remember some values
+// for later printout.
+
+      if (!FirstContact) {
+        FirstContact  = true;
+        SinkRate      =  compressSpeed;
+        GroundSpeed   =  Position->GetVel().Magnitude();
+        TakeoffReported = false;
+      }
+
+// If the takeoff run is starting, initialize.
+
+      if ((Position->GetVel().Magnitude() > 0.1) &&
+          (FCS->GetBrake(bgLeft) == 0) &&
+          (FCS->GetBrake(bgRight) == 0) &&
+          (FCS->GetThrottlePos(0) == 1) && !StartedGroundRun)
+      {
+        TakeoffDistanceTraveled = 0;
+        TakeoffDistanceTraveled50ft = 0;
+        StartedGroundRun = true;
+      }
+
+// 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.
+
+      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;
+      }
+
+      switch (eSteerType) {
+      case stSteer:
+        SteerAngle = -maxSteerAngle * FCS->GetDrCmd() * 0.01745; 
+        break;
+      case stFixed:
+        SteerAngle = 0.0;
+        break;
+      case stCaster:
+// Note to Jon: This is not correct for castering gear.  I'll fix it later.
+        SteerAngle = 0.0;
+        break;
+      default:
+        cerr << "Improper steering type membership detected for this gear." << endl;
+        break;
+      }
+
+// Transform the wheel velocities from the local axis system to the wheel axis system.
+// For now, steering angle is assumed to happen in the Local Z axis,
+// not the strut axis as it should be.  Will fix this later.
+
+      SinWheel      = sin(Rotation->Getpsi() + SteerAngle);
+      CosWheel      = cos(Rotation->Getpsi() + SteerAngle);
+      RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;
+      SideWhlVel    = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;
+
+// Calculate tire slip angle.
+
+      if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {
+        WheelSlip = 0.0;
+      } else if (fabs(RollingWhlVel) < 1.0) {
+        WheelSlip = 0.05*radtodeg*atan2(SideWhlVel, RollingWhlVel) + 0.95*WheelSlip;
+      } else {
+        WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);
+      }
+/*
+      double maxdeltaSlip = 0.5*deltaT;
+
+      if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {
+        WheelSlip = 0.0;
+      } else if (RollingWhlVel < 1.0) {
+        WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);
+        deltaSlip = WheelSlip - lastWheelSlip;
+        if (fabs(deltaSlip) > maxdeltaSlip) {
+          if (WheelSlip > lastWheelSlip) {
+            WheelSlip = lastWheelSlip + maxdeltaSlip;
+          } else if (WheelSlip < lastWheelSlip) {
+            WheelSlip = lastWheelSlip - maxdeltaSlip;
+          }
+        }
+      } else {
+        WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);
+      }
+
+      if ((WheelSlip < 0.0 && lastWheelSlip > 0.0) ||
+          (WheelSlip > 0.0 && lastWheelSlip < 0.0))
+      {
+        WheelSlip = 0.0;
+      }
+*/    
+      lastWheelSlip = WheelSlip;
+
+// Compute the sideforce coefficients using similar assumptions to LaRCSim for now.
+// Allow a maximum of 10 degrees tire slip angle before wheel slides.  At that point,
+// transition from static to dynamic friction.  There are more complicated formulations
+// of this that avoid the discrete jump.  Will fix this later.
+
+      if (fabs(WheelSlip) <= 20.0) {
+        FCoeff = staticFCoeff*WheelSlip/20.0;
+      } else if (fabs(WheelSlip) <= 40.0) {
+//        FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;
+        FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 20.0)/20.0 + 
+                  staticFCoeff*(40.0 - fabs(WheelSlip))/20.0)*fabs(WheelSlip)/WheelSlip;
+      } else {
+        FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;
+      }
+
+// 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.
+
+      vLocalForce(eZ) =  min(-compressLength * kSpring
+                             - compressSpeed * bDamp, (double)0.0);
+
+      MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));
+      MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));
+
+// Compute the forces in the wheel ground plane.
+
+      RollingForce = 0;
+      if (fabs(RollingWhlVel) > 1E-3) {
+        RollingForce = (1.0 - TirePressureNorm) * 30
+                       + vLocalForce(eZ) * BrakeFCoeff
+                       * fabs(RollingWhlVel)/RollingWhlVel;
+      }
+      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;
+
+// Note to Jon: At this point the forces will be too big when the airplane is
+// stopped or rolling to a stop.  We need to make sure that the gear forces just
+// balance out the non-gear forces when the airplane is stopped.  That way the
+// airplane won't start to accelerate until the non-gear/ forces are larger than
+// the gear forces.  I think that the proper fix should go into FGAircraft::FMGear.
+// This routine would only compute the local strut forces and return them to
+// FMGear. All of the gear forces would get adjusted in FMGear using the total
+// non-gear forces. Then the gear moments would be calculated. If strange things
+// start happening to the airplane during testing as it rolls to a stop, then we
+// need to implement this change.  I ran out of time to do it now but have the
+// equations.
+
+// Transform the forces back to the body frame and compute the moment.
+
+      vForce  = State->GetTl2b() * vLocalForce;
+      vMoment = vWhlBodyVec * vForce;
+
+    } else { // Gear is NOT compressed
+
+      WOW = false;
+
+      if (Position->GetDistanceAGL() > 200.0) {
+        FirstContact = false;
+        StartedGroundRun = false;
+        LandingReported = false;
+        LandingDistanceTraveled = 0.0;
+        MaximumStrutForce = MaximumStrutTravel = 0.0;
+      }
+
+      compressLength = 0.0; // reset compressLength to zero for data output validity
+    }
+
+    if (FirstContact) LandingDistanceTraveled += Position->GetVground()*deltaT;
+  
+    if (StartedGroundRun) {
+       TakeoffDistanceTraveled50ft += Position->GetVground()*deltaT;
+      if (WOW) TakeoffDistanceTraveled += Position->GetVground()*deltaT;
+    }
+
+    if (ReportEnable && Position->GetVground() <= 0.05 && !LandingReported) {
+      if (debug_lvl > 0) Report(erLand);
+    }
+
+    if (ReportEnable && !TakeoffReported &&
+       (vLocalGear(eZ) - Position->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)
+
+    if (compressLength > 500.0 ||
+        vForce.Magnitude() > 100000000.0 ||
+        vMoment.Magnitude() > 5000000000.0 ||
+        SinkRate > 1.4666*30)
+    {
+      PutMessage("Crash Detected: Simulation FREEZE.");
+      Exec->Freeze();
+    }
+  } 
+  return vForce; 
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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
+      cout << "    Name: "               << 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;
+      cout << "      Rolling Friction: " << rollingFCoeff << endl;
+      cout << "      Steering Type:    " << sSteerType    << endl;
+      cout << "      Grouping:         " << sBrakeGroup   << endl;
+      cout << "      Max Steer Angle:  " << maxSteerAngle << endl;
+      cout << "      Retractable:      " << sRetractable  << 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
+
index ddd442b5dad7e54c3757e70d76d4da952b8c4f7b..0d42129f17c849d6ff8de3fd5ec2a0ebfefd5f76 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-Module: FGMatrix33.cpp\r
-Author: Tony Peden, Jon Berndt, Mathias Frolich\r
-Date started: 1998\r
-Purpose: FGMatrix33 class\r
-Called by: Various\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-??/??/??   TP   Created\r
-03/16/2000 JSB  Added exception throwing\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGMatrix33.h"\r
-#include "FGColumnVector3.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_MATRIX33;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33::FGMatrix33(void)\r
-{\r
-  data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =\r
-    data[6] = data[7] = data[8] = 0.0;\r
-\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-ostream& operator<<(ostream& os, const FGMatrix33& M)\r
-{\r
-  for (unsigned int i=1; i<=M.Rows(); i++) {\r
-    for (unsigned int j=1; j<=M.Cols(); j++) {\r
-      if (i == M.Rows() && j == M.Cols())\r
-        os << M(i,j);\r
-      else\r
-        os << M(i,j) << ", ";\r
-    }\r
-  }\r
-  return os;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-istream& operator>>(istream& is, FGMatrix33& M)\r
-{\r
-  for (unsigned int i=1; i<=M.Rows(); i++) {\r
-    for (unsigned int j=1; j<=M.Cols(); j++) {\r
-      is >> M(i,j);\r
-    }\r
-  }\r
-  return is;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-double FGMatrix33::Determinant(void) const {\r
-  return Entry(1,1)*Entry(2,2)*Entry(3,3) + Entry(1,2)*Entry(2,3)*Entry(3,1)\r
-    + Entry(1,3)*Entry(2,1)*Entry(3,2) - Entry(1,3)*Entry(2,2)*Entry(3,1)\r
-    - Entry(1,2)*Entry(2,1)*Entry(3,3) - Entry(2,3)*Entry(3,2)*Entry(1,1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33 FGMatrix33::Inverse(void) const {\r
-  // Compute the inverse of a general matrix using Cramers rule.\r
-  // I guess googling for cramers rule gives tons of references\r
-  // for this. :)\r
-  double rdet = 1.0/Determinant();\r
-\r
-  double i11 = rdet*(Entry(2,2)*Entry(3,3)-Entry(2,3)*Entry(3,2));\r
-  double i21 = rdet*(Entry(2,3)*Entry(3,1)-Entry(2,1)*Entry(3,3));\r
-  double i31 = rdet*(Entry(2,1)*Entry(3,2)-Entry(2,2)*Entry(3,1));\r
-  double i12 = rdet*(Entry(1,3)*Entry(3,2)-Entry(1,2)*Entry(3,3));\r
-  double i22 = rdet*(Entry(1,1)*Entry(3,3)-Entry(1,3)*Entry(3,1));\r
-  double i32 = rdet*(Entry(1,2)*Entry(3,1)-Entry(1,1)*Entry(3,2));\r
-  double i13 = rdet*(Entry(1,2)*Entry(2,3)-Entry(1,3)*Entry(2,2));\r
-  double i23 = rdet*(Entry(1,3)*Entry(2,1)-Entry(1,1)*Entry(2,3));\r
-  double i33 = rdet*(Entry(1,1)*Entry(2,2)-Entry(1,2)*Entry(2,1));\r
-\r
-  return FGMatrix33( i11, i12, i13,\r
-                     i21, i22, i23,\r
-                     i31, i32, i33 );\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGMatrix33::InitMatrix(void)\r
-{\r
-  data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =\r
-    data[6] = data[7] = data[8] = 0.0;\r
-}\r
-\r
-// *****************************************************************************\r
-// binary operators ************************************************************\r
-// *****************************************************************************\r
-\r
-FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const\r
-{\r
-  return FGMatrix33( Entry(1,1) - M(1,1),\r
-                     Entry(1,2) - M(1,2),\r
-                     Entry(1,3) - M(1,3),\r
-                     Entry(2,1) - M(2,1),\r
-                     Entry(2,2) - M(2,2),\r
-                     Entry(2,3) - M(2,3),\r
-                     Entry(3,1) - M(3,1),\r
-                     Entry(3,2) - M(3,2),\r
-                     Entry(3,3) - M(3,3) );\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M)\r
-{\r
-  data[0] -= M.data[0];\r
-  data[1] -= M.data[1];\r
-  data[2] -= M.data[2];\r
-  data[3] -= M.data[3];\r
-  data[4] -= M.data[4];\r
-  data[5] -= M.data[5];\r
-  data[6] -= M.data[6];\r
-  data[7] -= M.data[7];\r
-  data[8] -= M.data[8];\r
-\r
-  return *this;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const\r
-{\r
-  return FGMatrix33( Entry(1,1) + M(1,1),\r
-                     Entry(1,2) + M(1,2),\r
-                     Entry(1,3) + M(1,3),\r
-                     Entry(2,1) + M(2,1),\r
-                     Entry(2,2) + M(2,2),\r
-                     Entry(2,3) + M(2,3),\r
-                     Entry(3,1) + M(3,1),\r
-                     Entry(3,2) + M(3,2),\r
-                     Entry(3,3) + M(3,3) );\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)\r
-{\r
-  Entry(1,1) += M(1,1);\r
-  Entry(1,2) += M(1,2);\r
-  Entry(1,3) += M(1,3);\r
-  Entry(2,1) += M(2,1);\r
-  Entry(2,2) += M(2,2);\r
-  Entry(2,3) += M(2,3);\r
-  Entry(3,1) += M(3,1);\r
-  Entry(3,2) += M(3,2);\r
-  Entry(3,3) += M(3,3);\r
-\r
-  return *this;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33 FGMatrix33::operator*(const double scalar) const\r
-{\r
-  return FGMatrix33( scalar * Entry(1,1),\r
-                     scalar * Entry(1,2),\r
-                     scalar * Entry(1,3),\r
-                     scalar * Entry(2,1),\r
-                     scalar * Entry(2,2),\r
-                     scalar * Entry(2,3),\r
-                     scalar * Entry(3,1),\r
-                     scalar * Entry(3,2),\r
-                     scalar * Entry(3,3) );\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33 operator*(double scalar, FGMatrix33 &M)\r
-{\r
-  return FGMatrix33( scalar * M(1,1),\r
-                     scalar * M(1,2),\r
-                     scalar * M(1,3),\r
-                     scalar * M(2,1),\r
-                     scalar * M(2,2),\r
-                     scalar * M(2,3),\r
-                     scalar * M(3,1),\r
-                     scalar * M(3,2),\r
-                     scalar * M(3,3) );\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33& FGMatrix33::operator*=(const double scalar)\r
-{\r
-  Entry(1,1) *= scalar;\r
-  Entry(1,2) *= scalar;\r
-  Entry(1,3) *= scalar;\r
-  Entry(2,1) *= scalar;\r
-  Entry(2,2) *= scalar;\r
-  Entry(2,3) *= scalar;\r
-  Entry(3,1) *= scalar;\r
-  Entry(3,2) *= scalar;\r
-  Entry(3,3) *= scalar;\r
-\r
-  return *this;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const\r
-{\r
-  // FIXME: Make compiler friendlier\r
-  FGMatrix33 Product;\r
-\r
-  Product(1,1) = Entry(1,1)*M(1,1) + Entry(1,2)*M(2,1) + Entry(1,3)*M(3,1);\r
-  Product(1,2) = Entry(1,1)*M(1,2) + Entry(1,2)*M(2,2) + Entry(1,3)*M(3,2);\r
-  Product(1,3) = Entry(1,1)*M(1,3) + Entry(1,2)*M(2,3) + Entry(1,3)*M(3,3);\r
-  Product(2,1) = Entry(2,1)*M(1,1) + Entry(2,2)*M(2,1) + Entry(2,3)*M(3,1);\r
-  Product(2,2) = Entry(2,1)*M(1,2) + Entry(2,2)*M(2,2) + Entry(2,3)*M(3,2);\r
-  Product(2,3) = Entry(2,1)*M(1,3) + Entry(2,2)*M(2,3) + Entry(2,3)*M(3,3);\r
-  Product(3,1) = Entry(3,1)*M(1,1) + Entry(3,2)*M(2,1) + Entry(3,3)*M(3,1);\r
-  Product(3,2) = Entry(3,1)*M(1,2) + Entry(3,2)*M(2,2) + Entry(3,3)*M(3,2);\r
-  Product(3,3) = Entry(3,1)*M(1,3) + Entry(3,2)*M(2,3) + Entry(3,3)*M(3,3);\r
-\r
-  return Product;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M)\r
-{\r
-  // FIXME: Make compiler friendlier\r
-  double a,b,c;\r
-\r
-  a = Entry(1,1); b=Entry(1,2); c=Entry(1,3);\r
-  Entry(1,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);\r
-  Entry(1,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);\r
-  Entry(1,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);\r
-\r
-  a = Entry(2,1); b=Entry(2,2); c=Entry(2,3);\r
-  Entry(2,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);\r
-  Entry(2,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);\r
-  Entry(2,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);\r
-\r
-  a = Entry(3,1); b=Entry(3,2); c=Entry(3,3);\r
-  Entry(3,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);\r
-  Entry(3,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);\r
-  Entry(3,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);\r
-\r
-  return *this;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33 FGMatrix33::operator/(const double scalar) const\r
-{\r
-  FGMatrix33 Quot;\r
-\r
-  if ( scalar != 0 ) {\r
-    double tmp = 1.0/scalar;\r
-    Quot(1,1) = Entry(1,1) * tmp;\r
-    Quot(1,2) = Entry(1,2) * tmp;\r
-    Quot(1,3) = Entry(1,3) * tmp;\r
-    Quot(2,1) = Entry(2,1) * tmp;\r
-    Quot(2,2) = Entry(2,2) * tmp;\r
-    Quot(2,3) = Entry(2,3) * tmp;\r
-    Quot(3,1) = Entry(3,1) * tmp;\r
-    Quot(3,2) = Entry(3,2) * tmp;\r
-    Quot(3,3) = Entry(3,3) * tmp;\r
-  } else {\r
-    MatrixException mE;\r
-    mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)";\r
-    throw mE;\r
-  }\r
-  return Quot;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGMatrix33& FGMatrix33::operator/=(const double scalar)\r
-{\r
-  if ( scalar != 0 ) {\r
-    double tmp = 1.0/scalar;\r
-    Entry(1,1) *= tmp;\r
-    Entry(1,2) *= tmp;\r
-    Entry(1,3) *= tmp;\r
-    Entry(2,1) *= tmp;\r
-    Entry(2,2) *= tmp;\r
-    Entry(2,3) *= tmp;\r
-    Entry(3,1) *= tmp;\r
-    Entry(3,2) *= tmp;\r
-    Entry(3,3) *= tmp;\r
-  } else {\r
-    MatrixException mE;\r
-    mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)";\r
-    throw mE;\r
-  }\r
-  return *this;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGMatrix33::T(void)\r
-{\r
-  for (unsigned int i=1; i<=3; i++) {\r
-    for (unsigned int j=i+1; j<=3; j++) {\r
-      double tmp = Entry(i,j);\r
-      Entry(i,j) = Entry(j,i);\r
-      Entry(j,i) = tmp;\r
-    }\r
-  }\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const {\r
-  double tmp1 = v(1)*Entry(1,1);\r
-  double tmp2 = v(1)*Entry(2,1);\r
-  double tmp3 = v(1)*Entry(3,1);\r
-\r
-  tmp1 += v(2)*Entry(1,2);\r
-  tmp2 += v(2)*Entry(2,2);\r
-  tmp3 += v(2)*Entry(3,2);\r
-\r
-  tmp1 += v(3)*Entry(1,3);\r
-  tmp2 += v(3)*Entry(2,3);\r
-  tmp3 += v(3)*Entry(3,3);\r
-\r
-  return FGColumnVector3( tmp1, tmp2, tmp3 );\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGMatrix33::Debug(int from)\r
-{\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-    if (from == 0) { // Constructor\r
-\r
-    }\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGMatrix33" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGMatrix33" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-}\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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;
+    }
+  }
+}
+}
index 54231a5ec390df99a7946993748362d0d26d63cf..15b76d8daf18e7a2d50e24d6643a681acf0729f1 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Module:       FGOutput.cpp\r
- Author:       Jon Berndt\r
- Date started: 12/02/98\r
- Purpose:      Manage output of sim parameters to file or stdout\r
- Called by:    FGSimExec\r
-\r
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-This is the place where you create output routines to dump data for perusal\r
-later.\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-12/02/98   JSB   Created\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGOutput.h"\r
-#include "FGState.h"\r
-#include "FGFDMExec.h"\r
-#include "FGAtmosphere.h"\r
-#include "FGFCS.h"\r
-#include "FGAerodynamics.h"\r
-#include "FGGroundReactions.h"\r
-#include "FGAircraft.h"\r
-#include "FGMassBalance.h"\r
-#include "FGTranslation.h"\r
-#include "FGRotation.h"\r
-#include "FGPosition.h"\r
-#include "FGAuxiliary.h"\r
-#include "FGInertial.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_OUTPUT;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)\r
-{\r
-  Name = "FGOutput";\r
-  sFirstPass = dFirstPass = true;\r
-  socket = 0;\r
-  Type = otNone;\r
-  Filename = "";\r
-  SubSystems = 0;\r
-  enabled = true;\r
-  outputInFileName = "";\r
-\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGOutput::~FGOutput()\r
-{\r
-  if (socket) delete socket;\r
-  for (unsigned int i=0; i<OutputProperties.size(); i++) delete OutputProperties[i];\r
-\r
-  Debug(1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-bool FGOutput::Run(void)\r
-{\r
-  if (enabled) {\r
-    if (!FGModel::Run()) {\r
-\r
-      if (Type == otSocket) {\r
-        SocketOutput();\r
-      } else if (Type == otCSV) {\r
-        DelimitedOutput(Filename);\r
-      } else if (Type == otTerminal) {\r
-        // Not done yet\r
-      } else if (Type == otNone) {\r
-        // Do nothing\r
-      } else {\r
-        // Not a valid type of output\r
-      }\r
-    return false;\r
-    } else {\r
-    return true;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGOutput::SetType(string type)\r
-{\r
-  if (type == "CSV") {\r
-    Type = otCSV;\r
-  } else if (type == "TABULAR") {\r
-    Type = otTab;\r
-  } else if (type == "SOCKET") {\r
-    Type = otSocket;\r
-  } else if (type == "TERMINAL") {\r
-    Type = otTerminal;\r
-  } else if (type != string("NONE")) {\r
-    Type = otUnknown;\r
-    cerr << "Unknown type of output specified in config file" << endl;\r
-  }\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGOutput::DelimitedOutput(string fname)\r
-{\r
-  streambuf* buffer;\r
-  string scratch = "";\r
-\r
-  if (fname == "COUT" || fname == "cout") {\r
-    buffer = cout.rdbuf();\r
-  } else {\r
-    datafile.open(fname.c_str());\r
-    buffer = datafile.rdbuf();\r
-  }\r
-\r
-  ostream outstream(buffer);\r
-\r
-  if (dFirstPass) {\r
-    outstream << "Time";\r
-    if (SubSystems & ssSimulation) {\r
-      // Nothing here, yet\r
-    }\r
-    if (SubSystems & ssAerosurfaces) {\r
-      outstream << ", ";\r
-      outstream << "Aileron Cmd, ";\r
-      outstream << "Elevator Cmd, ";\r
-      outstream << "Rudder Cmd, ";\r
-      outstream << "Flap Cmd, ";\r
-      outstream << "Left Aileron Pos, ";\r
-      outstream << "Right Aileron Pos, ";\r
-      outstream << "Elevator Pos, ";\r
-      outstream << "Rudder Pos, ";\r
-      outstream << "Flap Pos";\r
-    }\r
-    if (SubSystems & ssRates) {\r
-      outstream << ", ";\r
-      outstream << "P, Q, R, ";\r
-      outstream << "Pdot, Qdot, Rdot";\r
-    }\r
-    if (SubSystems & ssVelocities) {\r
-      outstream << ", ";\r
-      outstream << "QBar, ";\r
-      outstream << "Vtotal, ";\r
-      outstream << "UBody, VBody, WBody, ";\r
-      outstream << "UAero, VAero, WAero, ";\r
-      outstream << "Vn, Ve, Vd";\r
-    }\r
-    if (SubSystems & ssForces) {\r
-      outstream << ", ";\r
-      outstream << "Drag, Side, Lift, ";\r
-      outstream << "L/D, ";\r
-      outstream << "Xforce, Yforce, Zforce, ";\r
-      outstream << "xGravity, yGravity, zGravity, ";\r
-      outstream << "xCoriolis, yCoriolis, zCoriolis, ";\r
-      outstream << "xCentrifugal, yCentrifugal, zCentrifugal";\r
-    }\r
-    if (SubSystems & ssMoments) {\r
-      outstream << ", ";\r
-      outstream << "L, M, N";\r
-    }\r
-    if (SubSystems & ssAtmosphere) {\r
-      outstream << ", ";\r
-      outstream << "Rho, ";\r
-      outstream << "NWind, EWind, DWind";\r
-    }\r
-    if (SubSystems & ssMassProps) {\r
-      outstream << ", ";\r
-      outstream << "Ixx, ";\r
-      outstream << "Ixy, ";\r
-      outstream << "Ixz, ";\r
-      outstream << "Iyx, ";\r
-      outstream << "Iyy, ";\r
-      outstream << "Iyz, ";\r
-      outstream << "Izx, ";\r
-      outstream << "Izy, ";\r
-      outstream << "Izz, ";\r
-      outstream << "Mass, ";\r
-      outstream << "Xcg, Ycg, Zcg";\r
-    }\r
-    if (SubSystems & ssPosition) {\r
-      outstream << ", ";\r
-      outstream << "Altitude, ";\r
-      outstream << "Phi, Tht, Psi, ";\r
-      outstream << "Alpha, ";\r
-      outstream << "Beta, ";\r
-      outstream << "Latitude, ";\r
-      outstream << "Longitude, ";\r
-      outstream << "Distance AGL, ";\r
-      outstream << "Runway Radius";\r
-    }\r
-    if (SubSystems & ssCoefficients) {\r
-      scratch = Aerodynamics->GetCoefficientStrings();\r
-      if (scratch.length() != 0) outstream << ", " << scratch;\r
-    }\r
-    if (SubSystems & ssFCS) {\r
-      scratch = FCS->GetComponentStrings();\r
-      if (scratch.length() != 0) outstream << ", " << scratch;\r
-    }\r
-    if (SubSystems & ssGroundReactions) {\r
-      outstream << ", ";\r
-      outstream << GroundReactions->GetGroundReactionStrings();\r
-    }\r
-    if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {\r
-      outstream << ", ";\r
-      outstream << Propulsion->GetPropulsionStrings();\r
-    }\r
-    if (OutputProperties.size() > 0) {\r
-      for (unsigned int i=0;i<OutputProperties.size();i++) {\r
-        outstream << ", " << OutputProperties[i]->GetName();\r
-      }\r
-    }\r
-\r
-    outstream << endl;\r
-    dFirstPass = false;\r
-  }\r
-\r
-  outstream << State->Getsim_time();\r
-  if (SubSystems & ssSimulation) {\r
-  }\r
-  if (SubSystems & ssAerosurfaces) {\r
-    outstream << ", ";\r
-    outstream << FCS->GetDaCmd() << ", ";\r
-    outstream << FCS->GetDeCmd() << ", ";\r
-    outstream << FCS->GetDrCmd() << ", ";\r
-    outstream << FCS->GetDfCmd() << ", ";\r
-    outstream << FCS->GetDaLPos() << ", ";\r
-    outstream << FCS->GetDaRPos() << ", ";\r
-    outstream << FCS->GetDePos() << ", ";\r
-    outstream << FCS->GetDrPos() << ", ";\r
-    outstream << FCS->GetDfPos();\r
-  }\r
-  if (SubSystems & ssRates) {\r
-    outstream << ", ";\r
-    outstream << Rotation->GetPQR() << ", ";\r
-    outstream << Rotation->GetPQRdot();\r
-  }\r
-  if (SubSystems & ssVelocities) {\r
-    outstream << ", ";\r
-    outstream << Translation->Getqbar() << ", ";\r
-    outstream << Translation->GetVt() << ", ";\r
-    outstream << Translation->GetUVW() << ", ";\r
-    outstream << Translation->GetAeroUVW() << ", ";\r
-    outstream << Position->GetVel();\r
-  }\r
-  if (SubSystems & ssForces) {\r
-    outstream << ", ";\r
-    outstream << Aerodynamics->GetvFs() << ", ";\r
-    outstream << Aerodynamics->GetLoD() << ", ";\r
-    outstream << Aircraft->GetForces() << ", ";\r
-    outstream << Inertial->GetGravity() << ", ";\r
-    outstream << Inertial->GetCoriolis() << ", ";\r
-    outstream << Inertial->GetCentrifugal();\r
-  }\r
-  if (SubSystems & ssMoments) {\r
-    outstream << ", ";\r
-    outstream << Aircraft->GetMoments();\r
-  }\r
-  if (SubSystems & ssAtmosphere) {\r
-    outstream << ", ";\r
-    outstream << Atmosphere->GetDensity() << ", ";\r
-    outstream << Atmosphere->GetWindNED();\r
-  }\r
-  if (SubSystems & ssMassProps) {\r
-    outstream << ", ";\r
-    outstream << MassBalance->GetJ() << ", ";\r
-    outstream << MassBalance->GetMass() << ", ";\r
-    outstream << MassBalance->GetXYZcg();\r
-  }\r
-  if (SubSystems & ssPosition) {\r
-    outstream << ", ";\r
-    outstream << Position->Geth() << ", ";\r
-    outstream << Rotation->GetEuler() << ", ";\r
-    outstream << Translation->Getalpha() << ", ";\r
-    outstream << Translation->Getbeta() << ", ";\r
-    outstream << Position->GetLatitude() << ", ";\r
-    outstream << Position->GetLongitude() << ", ";\r
-    outstream << Position->GetDistanceAGL() << ", ";\r
-    outstream << Position->GetRunwayRadius();\r
-  }\r
-  if (SubSystems & ssCoefficients) {\r
-    scratch = Aerodynamics->GetCoefficientValues();\r
-    if (scratch.length() != 0) outstream << ", " << scratch;\r
-  }\r
-  if (SubSystems & ssFCS) {\r
-    scratch = FCS->GetComponentValues();\r
-    if (scratch.length() != 0) outstream << ", " << scratch;\r
-  }\r
-  if (SubSystems & ssGroundReactions) {\r
-    outstream << ", ";\r
-    outstream << GroundReactions->GetGroundReactionValues();\r
-  }\r
-  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {\r
-    outstream << ", ";\r
-    outstream << Propulsion->GetPropulsionValues();\r
-  }\r
-\r
-  for (unsigned int i=0;i<OutputProperties.size();i++) {\r
-    outstream << ", " << OutputProperties[i]->getDoubleValue();\r
-  }\r
-\r
-  outstream << endl;\r
-  outstream.flush();\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGOutput::SocketOutput(void)\r
-{\r
-  string asciiData;\r
-\r
-  if (socket == NULL) return;\r
-  if (!socket->GetConnectStatus()) return;\r
-\r
-  socket->Clear();\r
-  if (sFirstPass) {\r
-    socket->Append("<LABELS>");\r
-    socket->Append("Time");\r
-    socket->Append("Altitude");\r
-    socket->Append("Phi");\r
-    socket->Append("Tht");\r
-    socket->Append("Psi");\r
-    socket->Append("Rho");\r
-    socket->Append("Vtotal");\r
-    socket->Append("UBody");\r
-    socket->Append("VBody");\r
-    socket->Append("WBody");\r
-    socket->Append("UAero");\r
-    socket->Append("VAero");\r
-    socket->Append("WAero");\r
-    socket->Append("Vn");\r
-    socket->Append("Ve");\r
-    socket->Append("Vd");\r
-    socket->Append("Udot");\r
-    socket->Append("Vdot");\r
-    socket->Append("Wdot");\r
-    socket->Append("P");\r
-    socket->Append("Q");\r
-    socket->Append("R");\r
-    socket->Append("PDot");\r
-    socket->Append("QDot");\r
-    socket->Append("RDot");\r
-    socket->Append("Fx");\r
-    socket->Append("Fy");\r
-    socket->Append("Fz");\r
-    socket->Append("Latitude");\r
-    socket->Append("Longitude");\r
-    socket->Append("QBar");\r
-    socket->Append("Alpha");\r
-    socket->Append("L");\r
-    socket->Append("M");\r
-    socket->Append("N");\r
-    socket->Append("Throttle Position");\r
-    socket->Append("Left Aileron Position");\r
-    socket->Append("Right Aileron Position");\r
-    socket->Append("Elevator Position");\r
-    socket->Append("Rudder Position");\r
-    sFirstPass = false;\r
-    socket->Send();\r
-  }\r
-\r
-  socket->Clear();\r
-  socket->Append(State->Getsim_time());\r
-  socket->Append(Position->Geth());\r
-  socket->Append(Rotation->Getphi());\r
-  socket->Append(Rotation->Gettht());\r
-  socket->Append(Rotation->Getpsi());\r
-  socket->Append(Atmosphere->GetDensity());\r
-  socket->Append(Translation->GetVt());\r
-  socket->Append(Translation->GetUVW(eU));\r
-  socket->Append(Translation->GetUVW(eV));\r
-  socket->Append(Translation->GetUVW(eW));\r
-  socket->Append(Translation->GetAeroUVW(eU));\r
-  socket->Append(Translation->GetAeroUVW(eV));\r
-  socket->Append(Translation->GetAeroUVW(eW));\r
-  socket->Append(Position->GetVn());\r
-  socket->Append(Position->GetVe());\r
-  socket->Append(Position->GetVd());\r
-  socket->Append(Translation->GetUVWdot(eU));\r
-  socket->Append(Translation->GetUVWdot(eV));\r
-  socket->Append(Translation->GetUVWdot(eW));\r
-  socket->Append(Rotation->GetPQR(eP));\r
-  socket->Append(Rotation->GetPQR(eQ));\r
-  socket->Append(Rotation->GetPQR(eR));\r
-  socket->Append(Rotation->GetPQRdot(eP));\r
-  socket->Append(Rotation->GetPQRdot(eQ));\r
-  socket->Append(Rotation->GetPQRdot(eR));\r
-  socket->Append(Aircraft->GetForces(eX));\r
-  socket->Append(Aircraft->GetForces(eY));\r
-  socket->Append(Aircraft->GetForces(eZ));\r
-  socket->Append(Position->GetLatitude());\r
-  socket->Append(Position->GetLongitude());\r
-  socket->Append(Translation->Getqbar());\r
-  socket->Append(Translation->Getalpha());\r
-  socket->Append(Aircraft->GetMoments(eL));\r
-  socket->Append(Aircraft->GetMoments(eM));\r
-  socket->Append(Aircraft->GetMoments(eN));\r
-  socket->Append(FCS->GetThrottlePos(0));\r
-  socket->Append(FCS->GetDaLPos());\r
-  socket->Append(FCS->GetDaRPos());\r
-  socket->Append(FCS->GetDePos());\r
-  socket->Append(FCS->GetDrPos());\r
-  socket->Send();\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGOutput::SocketStatusOutput(string out_str)\r
-{\r
-  string asciiData;\r
-\r
-  if (socket == NULL) return;\r
-\r
-  socket->Clear();\r
-  asciiData = string("<STATUS>") + out_str;\r
-  socket->Append(asciiData.c_str());\r
-  socket->Send();\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-bool FGOutput::Load(FGConfigFile* AC_cfg)\r
-{\r
-  string token="", parameter="", separator="";\r
-  string name="", fname="";\r
-  int OutRate = 0;\r
-  FGConfigFile* Output_cfg;\r
-  string property;\r
-\r
-# ifndef macintosh\r
-    separator = "/";\r
-# else\r
-    separator = ";";\r
-# endif\r
-\r
-  name = AC_cfg->GetValue("NAME");\r
-  fname = AC_cfg->GetValue("FILE");\r
-  token = AC_cfg->GetValue("TYPE");\r
-  Output->SetType(token);\r
-\r
-#if defined( FG_WITH_JSBSIM_SOCKET ) || !defined( FGFS )\r
-  if (token == "SOCKET") {\r
-    socket = new FGfdmSocket("localhost",1138);\r
-  }\r
-#endif\r
-\r
-  if (!fname.empty()) {\r
-    outputInFileName = FDMExec->GetAircraftPath() + separator\r
-                        + FDMExec->GetModelName() + separator + fname + ".xml";\r
-    Output_cfg = new FGConfigFile(outputInFileName);\r
-    if (!Output_cfg->IsOpen()) {\r
-      cerr << "Could not open file: " << outputInFileName << endl;\r
-      return false;\r
-    }\r
-  } else {\r
-    Output_cfg = AC_cfg;\r
-  }\r
-  Output->SetFilename(name);\r
-\r
-  while ((token = Output_cfg->GetValue()) != string("/OUTPUT")) {\r
-    *Output_cfg >> parameter;\r
-    if (parameter == "RATE_IN_HZ") {\r
-      *Output_cfg >> OutRate;\r
-    }\r
-    if (parameter == "SIMULATION") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssSimulation;\r
-    }\r
-    if (parameter == "AEROSURFACES") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssAerosurfaces;\r
-    }\r
-    if (parameter == "RATES") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssRates;\r
-    }\r
-    if (parameter == "VELOCITIES") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssVelocities;\r
-    }\r
-    if (parameter == "FORCES") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssForces;\r
-    }\r
-    if (parameter == "MOMENTS") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssMoments;\r
-    }\r
-    if (parameter == "ATMOSPHERE") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssAtmosphere;\r
-    }\r
-    if (parameter == "MASSPROPS") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssMassProps;\r
-    }\r
-    if (parameter == "POSITION") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssPosition;\r
-    }\r
-    if (parameter == "COEFFICIENTS") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssCoefficients;\r
-    }\r
-    if (parameter == "GROUND_REACTIONS") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssGroundReactions;\r
-    }\r
-    if (parameter == "FCS") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssFCS;\r
-    }\r
-    if (parameter == "PROPULSION") {\r
-      *Output_cfg >> parameter;\r
-      if (parameter == "ON") SubSystems += ssPropulsion;\r
-    }\r
-    if (parameter == "PROPERTY") {\r
-      *Output_cfg >> property;\r
-      OutputProperties.push_back(PropertyManager->GetNode(property));\r
-    }\r
-\r
-    if (parameter == "EOF") break;\r
-  }\r
-\r
-  OutRate = OutRate>120?120:(OutRate<0?0:OutRate);\r
-  rate = (int)(0.5 + 1.0/(State->Getdt()*OutRate));\r
-\r
-  Debug(2);\r
-\r
-  return true;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGOutput::Debug(int from)\r
-{\r
-  string scratch="";\r
-\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-    if (from == 0) { // Constructor\r
-\r
-    }\r
-    if (from == 2) {\r
-      if (outputInFileName.empty())\r
-        cout << "  " << "Output parameters read inline" << endl;\r
-      else\r
-        cout << "    Output parameters read from file: " << outputInFileName << endl;\r
-\r
-      if (Filename == "cout" || Filename == "COUT") {\r
-        scratch = "    Log output goes to screen console";\r
-      } else if (!Filename.empty()) {\r
-        scratch = "    Log output goes to file: " + Filename;\r
-      }\r
-      switch (Type) {\r
-      case otCSV:\r
-        cout << scratch << " in CSV format output at rate " << 120/rate << " Hz" << endl;\r
-        break;\r
-      case otNone:\r
-        cout << "  No log output" << endl;\r
-        break;\r
-      }\r
-\r
-      if (SubSystems & ssSimulation)      cout << "    Simulation parameters logged" << endl;\r
-      if (SubSystems & ssAerosurfaces)    cout << "    Aerosurface parameters logged" << endl;\r
-      if (SubSystems & ssRates)           cout << "    Rate parameters logged" << endl;\r
-      if (SubSystems & ssVelocities)      cout << "    Velocity parameters logged" << endl;\r
-      if (SubSystems & ssForces)          cout << "    Force parameters logged" << endl;\r
-      if (SubSystems & ssMoments)         cout << "    Moments parameters logged" << endl;\r
-      if (SubSystems & ssAtmosphere)      cout << "    Atmosphere parameters logged" << endl;\r
-      if (SubSystems & ssMassProps)       cout << "    Mass parameters logged" << endl;\r
-      if (SubSystems & ssCoefficients)    cout << "    Coefficient parameters logged" << endl;\r
-      if (SubSystems & ssPosition)        cout << "    Position parameters logged" << endl;\r
-      if (SubSystems & ssGroundReactions) cout << "    Ground parameters logged" << endl;\r
-      if (SubSystems & ssFCS)             cout << "    FCS parameters logged" << endl;\r
-      if (SubSystems & ssPropulsion)      cout << "    Propulsion parameters logged" << endl;\r
-    }\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGOutput" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGOutput" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-}\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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 "FGTranslation.h"
+#include "FGRotation.h"
+#include "FGPosition.h"
+#include "FGAuxiliary.h"
+#include "FGInertial.h"
+
+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 = "";
+
+  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()) {
+
+      if (Type == otSocket) {
+        SocketOutput();
+      } else if (Type == otCSV) {
+        DelimitedOutput(Filename);
+      } else if (Type == otTerminal) {
+        // Not done yet
+      } else if (Type == otNone) {
+        // Do nothing
+      } else {
+        // Not a valid type of output
+      }
+    return false;
+    } else {
+    return true;
+    }
+  }
+  return false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGOutput::SetType(string type)
+{
+  if (type == "CSV") {
+    Type = otCSV;
+  } else if (type == "TABULAR") {
+    Type = otTab;
+  } 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 << ", ";
+      outstream << "Aileron Cmd, ";
+      outstream << "Elevator Cmd, ";
+      outstream << "Rudder Cmd, ";
+      outstream << "Flap Cmd, ";
+      outstream << "Left Aileron Pos, ";
+      outstream << "Right Aileron Pos, ";
+      outstream << "Elevator Pos, ";
+      outstream << "Rudder Pos, ";
+      outstream << "Flap Pos";
+    }
+    if (SubSystems & ssRates) {
+      outstream << ", ";
+      outstream << "P, Q, R, ";
+      outstream << "Pdot, Qdot, Rdot";
+    }
+    if (SubSystems & ssVelocities) {
+      outstream << ", ";
+      outstream << "QBar, ";
+      outstream << "Vtotal, ";
+      outstream << "UBody, VBody, WBody, ";
+      outstream << "UAero, VAero, WAero, ";
+      outstream << "Vn, Ve, Vd";
+    }
+    if (SubSystems & ssForces) {
+      outstream << ", ";
+      outstream << "Drag, Side, Lift, ";
+      outstream << "L/D, ";
+      outstream << "Xforce, Yforce, Zforce, ";
+      outstream << "xGravity, yGravity, zGravity, ";
+      outstream << "xCoriolis, yCoriolis, zCoriolis, ";
+      outstream << "xCentrifugal, yCentrifugal, zCentrifugal";
+    }
+    if (SubSystems & ssMoments) {
+      outstream << ", ";
+      outstream << "L, M, N";
+    }
+    if (SubSystems & ssAtmosphere) {
+      outstream << ", ";
+      outstream << "Rho, ";
+      outstream << "NWind, EWind, DWind";
+    }
+    if (SubSystems & ssMassProps) {
+      outstream << ", ";
+      outstream << "Ixx, ";
+      outstream << "Ixy, ";
+      outstream << "Ixz, ";
+      outstream << "Iyx, ";
+      outstream << "Iyy, ";
+      outstream << "Iyz, ";
+      outstream << "Izx, ";
+      outstream << "Izy, ";
+      outstream << "Izz, ";
+      outstream << "Mass, ";
+      outstream << "Xcg, Ycg, Zcg";
+    }
+    if (SubSystems & ssPosition) {
+      outstream << ", ";
+      outstream << "Altitude, ";
+      outstream << "Phi, Tht, Psi, ";
+      outstream << "Alpha, ";
+      outstream << "Beta, ";
+      outstream << "Latitude, ";
+      outstream << "Longitude, ";
+      outstream << "Distance AGL, ";
+      outstream << "Runway Radius";
+    }
+    if (SubSystems & ssCoefficients) {
+      scratch = Aerodynamics->GetCoefficientStrings();
+      if (scratch.length() != 0) outstream << ", " << scratch;
+    }
+    if (SubSystems & ssFCS) {
+      scratch = FCS->GetComponentStrings();
+      if (scratch.length() != 0) outstream << ", " << scratch;
+    }
+    if (SubSystems & ssGroundReactions) {
+      outstream << ", ";
+      outstream << GroundReactions->GetGroundReactionStrings();
+    }
+    if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
+      outstream << ", ";
+      outstream << Propulsion->GetPropulsionStrings();
+    }
+    if (OutputProperties.size() > 0) {
+      for (unsigned int i=0;i<OutputProperties.size();i++) {
+        outstream << ", " << OutputProperties[i]->GetName();
+      }
+    }
+
+    outstream << endl;
+    dFirstPass = false;
+  }
+
+  outstream << State->Getsim_time();
+  if (SubSystems & ssSimulation) {
+  }
+  if (SubSystems & ssAerosurfaces) {
+    outstream << ", ";
+    outstream << FCS->GetDaCmd() << ", ";
+    outstream << FCS->GetDeCmd() << ", ";
+    outstream << FCS->GetDrCmd() << ", ";
+    outstream << FCS->GetDfCmd() << ", ";
+    outstream << FCS->GetDaLPos() << ", ";
+    outstream << FCS->GetDaRPos() << ", ";
+    outstream << FCS->GetDePos() << ", ";
+    outstream << FCS->GetDrPos() << ", ";
+    outstream << FCS->GetDfPos();
+  }
+  if (SubSystems & ssRates) {
+    outstream << ", ";
+    outstream << Rotation->GetPQR() << ", ";
+    outstream << Rotation->GetPQRdot();
+  }
+  if (SubSystems & ssVelocities) {
+    outstream << ", ";
+    outstream << Translation->Getqbar() << ", ";
+    outstream << Translation->GetVt() << ", ";
+    outstream << Translation->GetUVW() << ", ";
+    outstream << Translation->GetAeroUVW() << ", ";
+    outstream << Position->GetVel();
+  }
+  if (SubSystems & ssForces) {
+    outstream << ", ";
+    outstream << Aerodynamics->GetvFs() << ", ";
+    outstream << Aerodynamics->GetLoD() << ", ";
+    outstream << Aircraft->GetForces() << ", ";
+    outstream << Inertial->GetGravity() << ", ";
+    outstream << Inertial->GetCoriolis() << ", ";
+    outstream << Inertial->GetCentrifugal();
+  }
+  if (SubSystems & ssMoments) {
+    outstream << ", ";
+    outstream << Aircraft->GetMoments();
+  }
+  if (SubSystems & ssAtmosphere) {
+    outstream << ", ";
+    outstream << Atmosphere->GetDensity() << ", ";
+    outstream << Atmosphere->GetWindNED();
+  }
+  if (SubSystems & ssMassProps) {
+    outstream << ", ";
+    outstream << MassBalance->GetJ() << ", ";
+    outstream << MassBalance->GetMass() << ", ";
+    outstream << MassBalance->GetXYZcg();
+  }
+  if (SubSystems & ssPosition) {
+    outstream << ", ";
+    outstream << Position->Geth() << ", ";
+    outstream << Rotation->GetEuler() << ", ";
+    outstream << Translation->Getalpha() << ", ";
+    outstream << Translation->Getbeta() << ", ";
+    outstream << Position->GetLatitude() << ", ";
+    outstream << Position->GetLongitude() << ", ";
+    outstream << Position->GetDistanceAGL() << ", ";
+    outstream << Position->GetRunwayRadius();
+  }
+  if (SubSystems & ssCoefficients) {
+    scratch = Aerodynamics->GetCoefficientValues();
+    if (scratch.length() != 0) outstream << ", " << scratch;
+  }
+  if (SubSystems & ssFCS) {
+    scratch = FCS->GetComponentValues();
+    if (scratch.length() != 0) outstream << ", " << scratch;
+  }
+  if (SubSystems & ssGroundReactions) {
+    outstream << ", ";
+    outstream << GroundReactions->GetGroundReactionValues();
+  }
+  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
+    outstream << ", ";
+    outstream << Propulsion->GetPropulsionValues();
+  }
+
+  for (unsigned int i=0;i<OutputProperties.size();i++) {
+    outstream << ", " << 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");
+    socket->Append("Longitude");
+    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(Position->Geth());
+  socket->Append(Rotation->Getphi());
+  socket->Append(Rotation->Gettht());
+  socket->Append(Rotation->Getpsi());
+  socket->Append(Atmosphere->GetDensity());
+  socket->Append(Translation->GetVt());
+  socket->Append(Translation->GetUVW(eU));
+  socket->Append(Translation->GetUVW(eV));
+  socket->Append(Translation->GetUVW(eW));
+  socket->Append(Translation->GetAeroUVW(eU));
+  socket->Append(Translation->GetAeroUVW(eV));
+  socket->Append(Translation->GetAeroUVW(eW));
+  socket->Append(Position->GetVn());
+  socket->Append(Position->GetVe());
+  socket->Append(Position->GetVd());
+  socket->Append(Translation->GetUVWdot(eU));
+  socket->Append(Translation->GetUVWdot(eV));
+  socket->Append(Translation->GetUVWdot(eW));
+  socket->Append(Rotation->GetPQR(eP));
+  socket->Append(Rotation->GetPQR(eQ));
+  socket->Append(Rotation->GetPQR(eR));
+  socket->Append(Rotation->GetPQRdot(eP));
+  socket->Append(Rotation->GetPQRdot(eQ));
+  socket->Append(Rotation->GetPQRdot(eR));
+  socket->Append(Aircraft->GetForces(eX));
+  socket->Append(Aircraft->GetForces(eY));
+  socket->Append(Aircraft->GetForces(eZ));
+  socket->Append(Position->GetLatitude());
+  socket->Append(Position->GetLongitude());
+  socket->Append(Translation->Getqbar());
+  socket->Append(Translation->Getalpha());
+  socket->Append(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;
+
+# ifndef macintosh
+    separator = "/";
+# else
+    separator = ";";
+# endif
+
+  name = AC_cfg->GetValue("NAME");
+  fname = AC_cfg->GetValue("FILE");
+  token = AC_cfg->GetValue("TYPE");
+  Output->SetType(token);
+
+#if defined( FG_WITH_JSBSIM_SOCKET ) || !defined( FGFS )
+  if (token == "SOCKET") {
+    socket = new FGfdmSocket("localhost",1138);
+  }
+#endif
+
+  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 += ssPosition;
+    }
+    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 & ssPosition)        cout << "    Position 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 (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;
+    }
+  }
+}
+}
index e33dba8210301c73d2b2d26095740f8866f72346..28b83b8f44e46b9bdec333a6c2ff95704a1470c2 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Module:       FGPosition.cpp\r
- Author:       Jon S. Berndt\r
- Date started: 01/05/99\r
- Purpose:      Integrate the EOM to determine instantaneous position\r
- Called by:    FGFDMExec\r
-\r
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-This class encapsulates the integration of rates and accelerations to get the\r
-current position of the aircraft.\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-01/05/99   JSB   Created\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-COMMENTS, REFERENCES,  and NOTES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling\r
-    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate\r
-    School, January 1994\r
-[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",\r
-    JSC 12960, July 1977\r
-[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at\r
-    NASA-Ames", NASA CR-2497, January 1975\r
-[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",\r
-    Wiley & Sons, 1979 ISBN 0-471-03032-5\r
-[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,\r
-    1982 ISBN 0-471-08936-2\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#ifdef FGFS\r
-#  include <simgear/compiler.h>\r
-#  ifdef SG_HAVE_STD_INCLUDES\r
-#    include <cmath>\r
-#    include <iomanip>\r
-#  else\r
-#    include <math.h>\r
-#    include <iomanip.h>\r
-#  endif\r
-#else\r
-#  if defined(sgi) && !defined(__GNUC__)\r
-#    include <math.h>\r
-#    if (_COMPILER_VERSION < 740)\r
-#      include <iomanip.h>\r
-#    else\r
-#      include <iomanip>\r
-#    endif\r
-#  else\r
-#    include <cmath>\r
-#    include <iomanip>\r
-#  endif\r
-#endif\r
-\r
-#include "FGPosition.h"\r
-#include "FGState.h"\r
-#include "FGFDMExec.h"\r
-#include "FGAircraft.h"\r
-#include "FGMassBalance.h"\r
-#include "FGTranslation.h"\r
-#include "FGRotation.h"\r
-#include "FGInertial.h"\r
-#include "FGPropertyManager.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_POSITION;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-FGPosition::FGPosition(FGFDMExec* fdmex) : FGModel(fdmex)\r
-{\r
-  Name = "FGPosition";\r
-  LongitudeDot = LatitudeDot = RadiusDot = 0.0;\r
-\r
-  for (int i=0;i<4;i++) {\r
-    LatitudeDot_prev[i]  = 0.0;\r
-    LongitudeDot_prev[i] = 0.0;\r
-    RadiusDot_prev[i]    = 0.0;\r
-  }\r
-\r
-  vVRPoffset.InitMatrix();\r
-\r
-  Longitude = Latitude = 0.0;\r
-  LongitudeVRP = LatitudeVRP = 0.0;\r
-  gamma = Vt = Vground = 0.0;\r
-  hoverbmac = hoverbcg = 0.0;\r
-  psigt = 0.0;\r
-  bind();\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGPosition::~FGPosition(void)\r
-{\r
-  unbind();\r
-  Debug(1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-bool FGPosition::InitModel(void)\r
-{\r
-  FGModel::InitModel();\r
-\r
-  h = 3.0;                                 // Est. height of aircraft cg off runway\r
-  SeaLevelRadius = Inertial->RefRadius();  // For initialization ONLY\r
-  Radius         = SeaLevelRadius + h;\r
-  RunwayRadius   = SeaLevelRadius;\r
-  DistanceAGL    = Radius - RunwayRadius;  // Geocentric\r
-  vRunwayNormal(3) = -1.0;                 // Initialized for standalone mode\r
-  b = 1;\r
-  return true;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-/*\r
-Purpose: Called on a schedule to perform Positioning algorithms\r
-Notes:   [TP] Make sure that -Vt <= hdot <= Vt, which, of course, should always\r
-         be the case\r
-         [JB] Run in standalone mode, SeaLevelRadius will be reference radius.\r
-               In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass.\r
-*/\r
-\r
-bool FGPosition::Run(void)\r
-{\r
-  double cosLat;\r
-  double hdot_Vt;\r
-\r
-  if (!FGModel::Run()) {\r
-    GetState();\r
-\r
-    Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) );\r
-\r
-    if (vVel(eNorth) == 0) psigt = 0;\r
-    else psigt =  atan2(vVel(eEast), vVel(eNorth));\r
-\r
-    if (psigt < 0.0) psigt += 2*M_PI;\r
-\r
-    Radius    = h + SeaLevelRadius;\r
-\r
-    cosLat = cos(Latitude);\r
-    if (cosLat != 0) LongitudeDot = vVel(eEast) / (Radius * cosLat);\r
-    LatitudeDot = vVel(eNorth) / Radius;\r
-    RadiusDot   = -vVel(eDown);\r
-\r
-    Longitude += State->Integrate(FGState::TRAPZ, dt*rate, LongitudeDot, LongitudeDot_prev);\r
-    Latitude  += State->Integrate(FGState::TRAPZ, dt*rate, LatitudeDot, LatitudeDot_prev);\r
-    Radius    += State->Integrate(FGState::TRAPZ, dt*rate, RadiusDot, RadiusDot_prev);\r
-\r
-    h = Radius - SeaLevelRadius;           // Geocentric\r
-\r
-    vVRPoffset = State->GetTb2l() * MassBalance->StructuralToBody(Aircraft->GetXYZvrp());\r
-\r
-    // vVRP  - the vector to the Visual Reference Point - now contains the\r
-    // offset from the CG to the VRP, in units of feet, in the Local coordinate\r
-    // frame, where X points north, Y points East, and Z points down. This needs\r
-    // to be converted to Lat/Lon/Alt, now.\r
-\r
-    if (cosLat != 0)\r
-      LongitudeVRP = vVRPoffset(eEast) / (Radius * cosLat) + Longitude;\r
-\r
-    LatitudeVRP = vVRPoffset(eNorth) / Radius + Latitude;\r
-    hVRP = h - vVRPoffset(eDown);\r
-/*\r
-cout << "Lat/Lon/Alt : " << Latitude << " / " << Longitude << " / " << h << endl;\r
-cout << "Lat/Lon/Alt VRP: " << LatitudeVRP << " / " << LongitudeVRP << " / " << hVRP << endl << endl;\r
-*/\r
-    DistanceAGL = Radius - RunwayRadius;   // Geocentric\r
-\r
-    hoverbcg = DistanceAGL/b;\r
-\r
-    vMac = State->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp());\r
-    hoverbmac = (DistanceAGL + vMac(3)) / b;\r
-\r
-    if (Vt > 0) {\r
-      hdot_Vt = RadiusDot/Vt;\r
-      if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);\r
-    } else {\r
-      gamma = 0.0;\r
-    }\r
-\r
-    return false;\r
-\r
-  } else {\r
-    return true;\r
-  }\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGPosition::GetState(void)\r
-{\r
-  dt = State->Getdt();\r
-\r
-  Vt        = Translation->GetVt();\r
-  vVel      = State->GetTb2l() * Translation->GetUVW();\r
-  vVelDot   = State->GetTb2l() * Translation->GetUVWdot();\r
-\r
-  b = Aircraft->GetWingSpan();\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGPosition::Seth(double tt)\r
-{\r
- h = tt;\r
- Radius    = h + SeaLevelRadius;\r
- DistanceAGL = Radius - RunwayRadius;   // Geocentric\r
- hoverbcg = DistanceAGL/b;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGPosition::SetDistanceAGL(double tt)\r
-{\r
-  DistanceAGL=tt;\r
-  Radius = RunwayRadius + DistanceAGL;\r
-  h = Radius - SeaLevelRadius;\r
-  hoverbcg = DistanceAGL/b;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGPosition::bind(void)\r
-{\r
-  PropertyManager->Tie("velocities/v-north-fps", this,\r
-                       &FGPosition::GetVn);\r
-  PropertyManager->Tie("velocities/v-east-fps", this,\r
-                       &FGPosition::GetVe);\r
-  PropertyManager->Tie("velocities/v-down-fps", this,\r
-                       &FGPosition::GetVd);\r
-  PropertyManager->Tie("velocities/vg-fps", this,\r
-                       &FGPosition::GetVground);\r
-  PropertyManager->Tie("flight-path/psi-gt-rad", this,\r
-                       &FGPosition::GetGroundTrack);\r
-  PropertyManager->Tie("position/h-sl-ft", this,\r
-                       &FGPosition::Geth,\r
-                       &FGPosition::Seth,\r
-                       true);\r
-  PropertyManager->Tie("velocities/h-dot-fps", this,\r
-                       &FGPosition::Gethdot);\r
-  PropertyManager->Tie("position/lat-gc-rad", this,\r
-                       &FGPosition::GetLatitude,\r
-                       &FGPosition::SetLatitude);\r
-  PropertyManager->Tie("position/lat-dot-gc-rad", this,\r
-                       &FGPosition::GetLatitudeDot);\r
-  PropertyManager->Tie("position/long-gc-rad", this,\r
-                       &FGPosition::GetLongitude,\r
-                       &FGPosition::SetLongitude,\r
-                       true);\r
-  PropertyManager->Tie("position/long-dot-gc-rad", this,\r
-                       &FGPosition::GetLongitudeDot);\r
-  PropertyManager->Tie("metrics/runway-radius", this,\r
-                       &FGPosition::GetRunwayRadius,\r
-                       &FGPosition::SetRunwayRadius);\r
-  PropertyManager->Tie("position/h-agl-ft", this,\r
-                       &FGPosition::GetDistanceAGL,\r
-                       &FGPosition::SetDistanceAGL);\r
-  PropertyManager->Tie("position/radius-to-vehicle-ft", this,\r
-                       &FGPosition::GetRadius);\r
-  PropertyManager->Tie("flight-path/gamma-rad", this,\r
-                       &FGPosition::GetGamma,\r
-                       &FGPosition::SetGamma);\r
-  PropertyManager->Tie("aero/h_b-cg-ft", this,\r
-                       &FGPosition::GetHOverBCG);\r
-  PropertyManager->Tie("aero/h_b-mac-ft", this,\r
-                       &FGPosition::GetHOverBMAC);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGPosition::unbind(void)\r
-{\r
-  PropertyManager->Untie("velocities/v-north-fps");\r
-  PropertyManager->Untie("velocities/v-east-fps");\r
-  PropertyManager->Untie("velocities/v-down-fps");\r
-  PropertyManager->Untie("velocities/vg-fps");\r
-  PropertyManager->Untie("flight-path/psi-gt-rad");\r
-  PropertyManager->Untie("position/h-sl-ft");\r
-  PropertyManager->Untie("velocities/h-dot-fps");\r
-  PropertyManager->Untie("position/lat-gc-rad");\r
-  PropertyManager->Untie("position/lat-dot-gc-rad");\r
-  PropertyManager->Untie("position/long-gc-rad");\r
-  PropertyManager->Untie("position/long-dot-gc-rad");\r
-  PropertyManager->Untie("metrics/runway-radius");\r
-  PropertyManager->Untie("position/h-agl-ft");\r
-  PropertyManager->Untie("position/radius-to-vehicle-ft");\r
-  PropertyManager->Untie("flight-path/gamma-rad");\r
-  PropertyManager->Untie("aero/h_b-cg-ft");\r
-  PropertyManager->Untie("aero/h_b-mac-ft");\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGPosition::Debug(int from)\r
-{\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-    if (from == 0) { // Constructor\r
-\r
-    }\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGPosition" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGPosition" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-}\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGPosition.cpp
+ Author:       Jon S. Berndt
+ Date started: 01/05/99
+ Purpose:      Integrate the EOM to determine instantaneous position
+ Called by:    FGFDMExec
+
+ ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+This class encapsulates the integration of rates and accelerations to get the
+current position of the aircraft.
+
+HISTORY
+--------------------------------------------------------------------------------
+01/05/99   JSB   Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+[1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
+    Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
+    School, January 1994
+[2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
+    JSC 12960, July 1977
+[3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
+    NASA-Ames", NASA CR-2497, January 1975
+[4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
+    Wiley & Sons, 1979 ISBN 0-471-03032-5
+[5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
+    1982 ISBN 0-471-08936-2
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+#  include <simgear/compiler.h>
+#  ifdef SG_HAVE_STD_INCLUDES
+#    include <cmath>
+#    include <iomanip>
+#  else
+#    include <math.h>
+#    include <iomanip.h>
+#  endif
+#else
+#  if defined(sgi) && !defined(__GNUC__)
+#    include <math.h>
+#    if (_COMPILER_VERSION < 740)
+#      include <iomanip.h>
+#    else
+#      include <iomanip>
+#    endif
+#  else
+#    include <cmath>
+#    include <iomanip>
+#  endif
+#endif
+
+#include "FGPosition.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+#include "FGAircraft.h"
+#include "FGMassBalance.h"
+#include "FGTranslation.h"
+#include "FGRotation.h"
+#include "FGInertial.h"
+#include "FGPropertyManager.h"
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_POSITION;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+FGPosition::FGPosition(FGFDMExec* fdmex) : FGModel(fdmex)
+{
+  Name = "FGPosition";
+  LongitudeDot = LatitudeDot = RadiusDot = 0.0;
+
+  for (int i=0;i<4;i++) {
+    LatitudeDot_prev[i]  = 0.0;
+    LongitudeDot_prev[i] = 0.0;
+    RadiusDot_prev[i]    = 0.0;
+  }
+
+  vVRPoffset.InitMatrix();
+
+  Longitude = Latitude = 0.0;
+  LongitudeVRP = LatitudeVRP = 0.0;
+  gamma = Vt = Vground = 0.0;
+  hoverbmac = hoverbcg = 0.0;
+  psigt = 0.0;
+  bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGPosition::~FGPosition(void)
+{
+  unbind();
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGPosition::InitModel(void)
+{
+  FGModel::InitModel();
+
+  h = 3.0;                                 // Est. height of aircraft cg off runway
+  SeaLevelRadius = Inertial->RefRadius();  // For initialization ONLY
+  Radius         = SeaLevelRadius + h;
+  RunwayRadius   = SeaLevelRadius;
+  DistanceAGL    = Radius - RunwayRadius;  // Geocentric
+  vRunwayNormal(3) = -1.0;                 // Initialized for standalone mode
+  b = 1;
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/*
+Purpose: Called on a schedule to perform Positioning algorithms
+Notes:   [TP] Make sure that -Vt <= hdot <= Vt, which, of course, should always
+         be the case
+         [JB] Run in standalone mode, SeaLevelRadius will be reference radius.
+               In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass.
+*/
+
+bool FGPosition::Run(void)
+{
+  double cosLat;
+  double hdot_Vt;
+
+  if (!FGModel::Run()) {
+    GetState();
+
+    Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) );
+
+    if (vVel(eNorth) == 0) psigt = 0;
+    else psigt =  atan2(vVel(eEast), vVel(eNorth));
+
+    if (psigt < 0.0) psigt += 2*M_PI;
+
+    Radius    = h + SeaLevelRadius;
+
+    cosLat = cos(Latitude);
+    if (cosLat != 0) LongitudeDot = vVel(eEast) / (Radius * cosLat);
+    LatitudeDot = vVel(eNorth) / Radius;
+    RadiusDot   = -vVel(eDown);
+
+    Longitude += State->Integrate(FGState::TRAPZ, dt*rate, LongitudeDot, LongitudeDot_prev);
+    Latitude  += State->Integrate(FGState::TRAPZ, dt*rate, LatitudeDot, LatitudeDot_prev);
+    Radius    += State->Integrate(FGState::TRAPZ, dt*rate, RadiusDot, RadiusDot_prev);
+
+    h = Radius - SeaLevelRadius;           // Geocentric
+
+    vVRPoffset = State->GetTb2l() * MassBalance->StructuralToBody(Aircraft->GetXYZvrp());
+
+    // vVRP  - the vector to the Visual Reference Point - now contains the
+    // offset from the CG to the VRP, in units of feet, in the Local coordinate
+    // frame, where X points north, Y points East, and Z points down. This needs
+    // to be converted to Lat/Lon/Alt, now.
+
+    if (cosLat != 0)
+      LongitudeVRP = vVRPoffset(eEast) / (Radius * cosLat) + Longitude;
+
+    LatitudeVRP = vVRPoffset(eNorth) / Radius + Latitude;
+    hVRP = h - vVRPoffset(eDown);
+/*
+cout << "Lat/Lon/Alt : " << Latitude << " / " << Longitude << " / " << h << endl;
+cout << "Lat/Lon/Alt VRP: " << LatitudeVRP << " / " << LongitudeVRP << " / " << hVRP << endl << endl;
+*/
+    DistanceAGL = Radius - RunwayRadius;   // Geocentric
+
+    hoverbcg = DistanceAGL/b;
+
+    vMac = State->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp());
+    hoverbmac = (DistanceAGL + vMac(3)) / b;
+
+    if (Vt > 0) {
+      hdot_Vt = RadiusDot/Vt;
+      if (fabs(hdot_Vt) <= 1) gamma = asin(hdot_Vt);
+    } else {
+      gamma = 0.0;
+    }
+
+    return false;
+
+  } else {
+    return true;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPosition::GetState(void)
+{
+  dt = State->Getdt();
+
+  Vt        = Translation->GetVt();
+  vVel      = State->GetTb2l() * Translation->GetUVW();
+  vVelDot   = State->GetTb2l() * Translation->GetUVWdot();
+
+  b = Aircraft->GetWingSpan();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPosition::Seth(double tt)
+{
+ h = tt;
+ Radius    = h + SeaLevelRadius;
+ DistanceAGL = Radius - RunwayRadius;   // Geocentric
+ hoverbcg = DistanceAGL/b;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPosition::SetDistanceAGL(double tt)
+{
+  DistanceAGL=tt;
+  Radius = RunwayRadius + DistanceAGL;
+  h = Radius - SeaLevelRadius;
+  hoverbcg = DistanceAGL/b;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPosition::bind(void)
+{
+  PropertyManager->Tie("velocities/v-north-fps", this,
+                       &FGPosition::GetVn);
+  PropertyManager->Tie("velocities/v-east-fps", this,
+                       &FGPosition::GetVe);
+  PropertyManager->Tie("velocities/v-down-fps", this,
+                       &FGPosition::GetVd);
+  PropertyManager->Tie("velocities/vg-fps", this,
+                       &FGPosition::GetVground);
+  PropertyManager->Tie("flight-path/psi-gt-rad", this,
+                       &FGPosition::GetGroundTrack);
+  PropertyManager->Tie("position/h-sl-ft", this,
+                       &FGPosition::Geth,
+                       &FGPosition::Seth,
+                       true);
+  PropertyManager->Tie("velocities/h-dot-fps", this,
+                       &FGPosition::Gethdot);
+  PropertyManager->Tie("position/lat-gc-rad", this,
+                       &FGPosition::GetLatitude,
+                       &FGPosition::SetLatitude);
+  PropertyManager->Tie("position/lat-dot-gc-rad", this,
+                       &FGPosition::GetLatitudeDot);
+  PropertyManager->Tie("position/long-gc-rad", this,
+                       &FGPosition::GetLongitude,
+                       &FGPosition::SetLongitude,
+                       true);
+  PropertyManager->Tie("position/long-dot-gc-rad", this,
+                       &FGPosition::GetLongitudeDot);
+  PropertyManager->Tie("metrics/runway-radius", this,
+                       &FGPosition::GetRunwayRadius,
+                       &FGPosition::SetRunwayRadius);
+  PropertyManager->Tie("position/h-agl-ft", this,
+                       &FGPosition::GetDistanceAGL,
+                       &FGPosition::SetDistanceAGL);
+  PropertyManager->Tie("position/radius-to-vehicle-ft", this,
+                       &FGPosition::GetRadius);
+  PropertyManager->Tie("flight-path/gamma-rad", this,
+                       &FGPosition::GetGamma,
+                       &FGPosition::SetGamma);
+  PropertyManager->Tie("aero/h_b-cg-ft", this,
+                       &FGPosition::GetHOverBCG);
+  PropertyManager->Tie("aero/h_b-mac-ft", this,
+                       &FGPosition::GetHOverBMAC);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPosition::unbind(void)
+{
+  PropertyManager->Untie("velocities/v-north-fps");
+  PropertyManager->Untie("velocities/v-east-fps");
+  PropertyManager->Untie("velocities/v-down-fps");
+  PropertyManager->Untie("velocities/vg-fps");
+  PropertyManager->Untie("flight-path/psi-gt-rad");
+  PropertyManager->Untie("position/h-sl-ft");
+  PropertyManager->Untie("velocities/h-dot-fps");
+  PropertyManager->Untie("position/lat-gc-rad");
+  PropertyManager->Untie("position/lat-dot-gc-rad");
+  PropertyManager->Untie("position/long-gc-rad");
+  PropertyManager->Untie("position/long-dot-gc-rad");
+  PropertyManager->Untie("metrics/runway-radius");
+  PropertyManager->Untie("position/h-agl-ft");
+  PropertyManager->Untie("position/radius-to-vehicle-ft");
+  PropertyManager->Untie("flight-path/gamma-rad");
+  PropertyManager->Untie("aero/h_b-cg-ft");
+  PropertyManager->Untie("aero/h_b-mac-ft");
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    The bitmasked value choices are as follows:
+//    unset: In this case (the default) JSBSim would only print
+//       out the normally expected messages, essentially echoing
+//       the config files as they are read. If the environment
+//       variable is not set, debug_lvl is set to 1 internally
+//    0: This requests JSBSim not to output any messages
+//       whatsoever.
+//    1: This value explicity requests the normal JSBSim
+//       startup messages
+//    2: This value asks for a message to be printed out when
+//       a class is instantiated
+//    4: When this value is set, a message is displayed when a
+//       FGModel object executes its Run() method
+//    8: When this value is set, various runtime state variables
+//       are printed out periodically
+//    16: When set various parameters are sanity checked and
+//       a message is printed out when they go out of bounds
+
+void FGPosition::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGPosition" << endl;
+    if (from == 1) cout << "Destroyed:    FGPosition" << endl;
+  }
+  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
+  }
+  if (debug_lvl & 8 ) { // Runtime state variables
+  }
+  if (debug_lvl & 16) { // Sanity checking
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+}
index bcb3b1bd770ed9a21927afe568e676a2a7646f5d..b9fcb62afa9da5d86a240af02e1830714118b1af 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Module:       FGCondition.cpp\r
- Author:       Jon S. Berndt\r
- Date started: 1/2/2003\r
-\r
- -------------- Copyright (C) 2003 Jon S. Berndt (jsb@hal-pc.org) --------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-COMMENTS, REFERENCES,  and NOTES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGCondition.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_CONDITION;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-string FGCondition::indent = "        ";\r
-\r
-\r
-FGCondition::FGCondition(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManager) :\r
-  PropertyManager(PropertyManager)\r
-{\r
-  string property1, property2;\r
-\r
-  mComparison["EQ"] = eEQ;\r
-  mComparison["NE"] = eNE;\r
-  mComparison["GT"] = eGT;\r
-  mComparison["GE"] = eGE;\r
-  mComparison["LT"] = eLT;\r
-  mComparison["LE"] = eLE;\r
-  mComparison["=="] = eEQ;\r
-  mComparison["!="] = eNE;\r
-  mComparison[">"]  = eGT;\r
-  mComparison[">="] = eGE;\r
-  mComparison["<"]  = eLT;\r
-  mComparison["<="] = eLE;\r
-\r
-  TestParam1  = TestParam2 = 0L;\r
-  TestValue   = 0.0;\r
-  Comparison  = ecUndef;\r
-  Logic       = elUndef;\r
-  conditions.clear();\r
-\r
-  if (AC_cfg->GetValue("CONDITION_GROUP").empty()) {  // define a condition\r
-\r
-    *AC_cfg >> property1 >> conditional >> property2;\r
-    TestParam1 = PropertyManager->GetNode(property1, true);\r
-    Comparison = mComparison[conditional];\r
-\r
-    if (property2.find_first_not_of("-.0123456789eE") == string::npos) {\r
-      TestValue = atof(property2.c_str());\r
-    } else {\r
-      TestParam2 = PropertyManager->GetNode(property2, true);\r
-    }\r
-\r
-    isGroup = false;\r
-\r
-  } else { // define a condition group\r
-\r
-    if (AC_cfg->GetValue("LOGIC") == "OR")       Logic = eOR;\r
-    else if (AC_cfg->GetValue("LOGIC") == "AND") Logic = eAND;\r
-\r
-    AC_cfg->GetNextConfigLine();\r
-    while (AC_cfg->GetValue() != string("/CONDITION_GROUP")) {\r
-      conditions.push_back(FGCondition(AC_cfg, PropertyManager));\r
-    }\r
-    isGroup = true;\r
-    AC_cfg->GetNextConfigLine();\r
-  }\r
-\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGCondition::~FGCondition(void)\r
-{\r
-  Debug(1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-bool FGCondition::Evaluate(void )\r
-{\r
-  vector <FGCondition>::iterator iConditions;\r
-  bool pass = false;\r
-  double compareValue;\r
-\r
-  if (Logic == eAND) {\r
-\r
-    iConditions = conditions.begin();\r
-    pass = true;\r
-    while (iConditions < conditions.end()) {\r
-      if (!iConditions->Evaluate()) pass = false;\r
-      *iConditions++;\r
-    }\r
-\r
-  } else if (Logic == eOR) {\r
-\r
-    pass = false;\r
-    while (iConditions < conditions.end()) {\r
-      if (iConditions->Evaluate()) pass = true;\r
-      *iConditions++;\r
-    }\r
-\r
-  } else {\r
-\r
-    if (TestParam2 != 0L) compareValue = TestParam2->getDoubleValue();\r
-    else compareValue = TestValue;\r
-\r
-    switch (Comparison) {\r
-    case ecUndef:\r
-      cerr << "Undefined comparison operator." << endl;\r
-      break;\r
-    case eEQ:\r
-      pass = TestParam1->getDoubleValue() == compareValue;\r
-      break;\r
-    case eNE:\r
-      pass = TestParam1->getDoubleValue() != compareValue;\r
-      break;\r
-    case eGT:\r
-      pass = TestParam1->getDoubleValue() > compareValue;\r
-      break;\r
-    case eGE:\r
-      pass = TestParam1->getDoubleValue() >= compareValue;\r
-      break;\r
-    case eLT:\r
-      pass = TestParam1->getDoubleValue() < compareValue;\r
-      break;\r
-    case eLE:\r
-      pass = TestParam1->getDoubleValue() <= compareValue;\r
-      break;\r
-    default:\r
-     cerr << "Unknown comparison operator." << endl;\r
-    }\r
-  }\r
-\r
-  return pass;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-void FGCondition::PrintCondition(void )\r
-{\r
-  vector <FGCondition>::iterator iConditions;\r
-  string scratch;\r
-\r
-  if (isGroup) {\r
-    switch(Logic) {\r
-    case (elUndef):\r
-      scratch = " UNSET";\r
-      cerr << "unset logic for test condition" << endl;\r
-      break;\r
-    case (eAND):\r
-      scratch = " if all of the following are true";\r
-      break;\r
-    case (eOR):\r
-      scratch = " if any of the following are true:";\r
-      break;\r
-    default:\r
-      scratch = " UNKNOWN";\r
-      cerr << "Unknown logic for test condition" << endl;\r
-    }\r
-\r
-    iConditions = conditions.begin();\r
-    cout << scratch << endl;\r
-    while (iConditions < conditions.end()) {\r
-      iConditions->PrintCondition();\r
-      *iConditions++;\r
-    }\r
-  } else {\r
-    if (TestParam2 != 0L)\r
-      cout << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName();\r
-    else\r
-      cout << TestParam1->GetName() << " " << conditional << " " << TestValue;\r
-  }\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGCondition::Debug(int from)\r
-{\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-    if (from == 0) { // Constructor\r
-\r
-    }\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGCondition" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGCondition" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-\r
-} //namespace JSBSim\r
-\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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(FGConfigFile* AC_cfg, FGPropertyManager* PropertyManager) :
+  PropertyManager(PropertyManager)
+{
+  string property1, property2;
+
+  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;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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
+
index 8557d099cd407d42434b31e20d13ee28cee13d70..cf323fcb64e11e6d83286e9addccb1617b2495a0 100644 (file)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Module:       FGSwitch.cpp\r
- Author:       Jon S. Berndt\r
- Date started: 4/2000\r
-\r
- ------------- Copyright (C) 2000 -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-COMMENTS, REFERENCES,  and NOTES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-The SWITCH component is defined as follows (see the API documentation for more\r
-information):\r
-\r
-<COMPONENT NAME="switch1" TYPE="SWITCH">\r
-  <TEST LOGIC="{AND|OR|DEFAULT}" OUTPUT="{property|value}">\r
-    {property} {conditional} {property|value}\r
-    <CONDITION_GROUP LOGIC="{AND|OR}">\r
-      {property} {conditional} {property|value}\r
-      ...\r
-    </CONDITION_GROUP>\r
-    ...\r
-  </TEST>\r
-  <TEST LOGIC="{AND|OR}" OUTPUT="{property|value}">\r
-    {property} {conditional} {property|value}\r
-    ...\r
-  </TEST>\r
-  ...\r
-</COMPONENT>\r
-\r
-Also, see the header file (FGSwitch.h) for further details.\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGSwitch.h"\r
-\r
-namespace JSBSim {\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_SWITCH;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-\r
-FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),\r
-                                                       AC_cfg(AC_cfg)\r
-{\r
-  string token, value;\r
-  struct test *current_test;\r
-  struct FGCondition *current_condition;\r
-\r
-  Type = AC_cfg->GetValue("TYPE");\r
-  Name = AC_cfg->GetValue("NAME");\r
-\r
-  AC_cfg->GetNextConfigLine();\r
-  while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {\r
-\r
-    // See the above documentation, or the API docs, for information on what\r
-    // the SWITCH component is supposed to look like in the configuration file.\r
-    // Below, the switch component is read in.\r
-\r
-    if (token == "TEST") {\r
-      tests.push_back(test());\r
-      current_test = &tests.back();\r
-\r
-      if (AC_cfg->GetValue("LOGIC") == "OR") {\r
-        current_test->Logic = eOR;\r
-      } else if (AC_cfg->GetValue("LOGIC") == "AND") {\r
-        current_test->Logic = eAND;\r
-      } else if (AC_cfg->GetValue("LOGIC") == "DEFAULT") {\r
-        current_test->Logic = eDefault;\r
-      } else { // error\r
-        cerr << "Unrecognized LOGIC token  in switch component: " << Name << endl;\r
-      }\r
-\r
-      value = AC_cfg->GetValue("VALUE");\r
-      if (value.empty()) {\r
-        cerr << "No VALUE supplied for switch component: " << Name << endl;\r
-      } else {\r
-        if (value.find_first_not_of("-.0123456789eE") == string::npos) {\r
-          // if true (and execution falls into this block), "value" is a number.\r
-          current_test->OutputVal = atof(value.c_str());\r
-        } else {\r
-          // "value" must be a property if execution passes to here.\r
-          if (value[0] == '-') {\r
-            current_test->sign = -1.0;\r
-            value.erase(0,1);\r
-          } else {\r
-            current_test->sign = 1.0;\r
-          }\r
-          current_test->OutputProp = PropertyManager->GetNode(value);\r
-        }\r
-      }\r
-\r
-      AC_cfg->GetNextConfigLine();\r
-      while (AC_cfg->GetValue() != string("/TEST")) {\r
-        current_test->conditions.push_back(FGCondition(AC_cfg, PropertyManager));\r
-      }\r
-    }\r
-    AC_cfg->GetNextConfigLine();\r
-  }\r
-\r
-  FGFCSComponent::bind();\r
-\r
-  Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGSwitch::~FGSwitch()\r
-{\r
-  Debug(1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-bool FGSwitch::Run(void )\r
-{\r
-  vector <test>::iterator iTests = tests.begin();\r
-  vector <FGCondition>::iterator iConditions;\r
-  bool pass = false;\r
-\r
-  FGFCSComponent::Run(); // call the base class for initialization of Input\r
-\r
-  while (iTests < tests.end()) {\r
-    iConditions = iTests->conditions.begin();\r
-\r
-    if (iTests->Logic == eDefault) {\r
-      Output = iTests->GetValue();\r
-    } else if (iTests->Logic == eAND) {\r
-      pass = true;\r
-      while (iConditions < iTests->conditions.end()) {\r
-        if (!iConditions->Evaluate()) pass = false;\r
-        *iConditions++;\r
-      }\r
-    } else if (iTests->Logic == eOR) {\r
-      pass = false;\r
-      while (iConditions < iTests->conditions.end()) {\r
-        if (iConditions->Evaluate()) pass = true;\r
-        *iConditions++;\r
-      }\r
-    } else {\r
-      cerr << "Invalid logic test" << endl;\r
-    }\r
-\r
-    if (pass) {\r
-      Output = iTests->GetValue();\r
-      break;\r
-    }\r
-    *iTests++;\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-//    The bitmasked value choices are as follows:\r
-//    unset: In this case (the default) JSBSim would only print\r
-//       out the normally expected messages, essentially echoing\r
-//       the config files as they are read. If the environment\r
-//       variable is not set, debug_lvl is set to 1 internally\r
-//    0: This requests JSBSim not to output any messages\r
-//       whatsoever.\r
-//    1: This value explicity requests the normal JSBSim\r
-//       startup messages\r
-//    2: This value asks for a message to be printed out when\r
-//       a class is instantiated\r
-//    4: When this value is set, a message is displayed when a\r
-//       FGModel object executes its Run() method\r
-//    8: When this value is set, various runtime state variables\r
-//       are printed out periodically\r
-//    16: When set various parameters are sanity checked and\r
-//       a message is printed out when they go out of bounds\r
-\r
-void FGSwitch::Debug(int from)\r
-{\r
-  vector <test>::iterator iTests = tests.begin();\r
-  vector <FGCondition>::iterator iConditions;\r
-  string comp, scratch;\r
-  string indent = "        ";\r
-  bool first = false;\r
-\r
-  if (debug_lvl <= 0) return;\r
-\r
-  if (debug_lvl & 1) { // Standard console startup message output\r
-    if (from == 0) { // Constructor\r
-      while (iTests < tests.end()) {\r
-\r
-        scratch = " if ";\r
-\r
-        switch(iTests->Logic) {\r
-        case (elUndef):\r
-          comp = " UNSET ";\r
-          cerr << "Unset logic for test condition" << endl;\r
-          break;\r
-        case (eAND):\r
-          comp = " AND ";\r
-          break;\r
-        case (eOR):\r
-          comp=" OR ";\r
-          break;\r
-        case (eDefault):\r
-          scratch = " by default.";\r
-          break;\r
-        default:\r
-          comp = " UNKNOWN ";\r
-          cerr << "Unknown logic for test condition" << endl;\r
-        }\r
-\r
-        if (iTests->OutputProp != 0L)\r
-          if (iTests->sign < 0)\r
-            cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;\r
-          else\r
-            cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;\r
-        else\r
-          cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;\r
-\r
-        iConditions = iTests->conditions.begin();\r
-        first = true;\r
-        while (iConditions < iTests->conditions.end()) {\r
-          if (!first) cout << indent << comp << " ";\r
-          else cout << indent << " ";\r
-          first = false;\r
-          iConditions->PrintCondition();\r
-          cout << endl;\r
-          *iConditions++;\r
-        }\r
-        cout << endl;\r
-        *iTests++;\r
-      }\r
-    }\r
-  }\r
-  if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
-    if (from == 0) cout << "Instantiated: FGSwitch" << endl;\r
-    if (from == 1) cout << "Destroyed:    FGSwitch" << endl;\r
-  }\r
-  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
-  }\r
-  if (debug_lvl & 8 ) { // Runtime state variables\r
-  }\r
-  if (debug_lvl & 16) { // Sanity checking\r
-  }\r
-  if (debug_lvl & 64) {\r
-    if (from == 0) { // Constructor\r
-      cout << IdSrc << endl;\r
-      cout << IdHdr << endl;\r
-    }\r
-  }\r
-}\r
-\r
-} //namespace JSBSim\r
-\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ 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, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
+                                                       AC_cfg(AC_cfg)
+{
+  string token, value;
+  struct test *current_test;
+  struct FGCondition *current_condition;
+
+  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();
+  }
+
+  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++;
+  }
+
+  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 (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
+