-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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
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)
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)
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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;
+ }
+ }
+}
+}
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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
+
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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
+
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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;
+ }
+ }
+}
+}
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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;
+ }
+ }
+}
+}
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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;
+ }
+ }
+}
+}
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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
+
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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
+