]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/FGForce.h
Updated to match changes in radiostack.[ch]xx
[flightgear.git] / src / FDM / JSBSim / FGForce.h
index 6a765876f3236e13d42d16c63ca89c8a86748bb4..dfacc4a194c4f990c97a761c40c51e610a05bea7 100644 (file)
@@ -57,55 +57,236 @@ SENTRY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FORCE "$Header"
+#define ID_FORCE "$Id$"
 
 #include "FGFDMExec.h"
-#include "FGMatrix.h"
+#include "FGJSBBase.h"
+#include "FGMatrix33.h"
+#include "FGColumnVector3.h"
+#include "FGColumnVector4.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
+COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-typedef enum { tNone, tWindBody, tLocalBody, tCustom } TransformType;
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-class FGForce {
+/** Utility class that aids in the conversion of forces between coordinate systems
+    and calculation of moments.
+<br><h3>Resolution of Applied Forces into Moments and Body Axes Components</h3>
+<br><p>
+All forces acting on the aircraft that cannot be considered a change in weight
+need to be resolved into body axis components so that the aircraft acceleration
+vectors, both translational and rotational, can be computed. Furthermore, the
+moments produced by each force that does not act at a location corresponding to
+the center of gravity also need to be computed. Unfortunately, the math required
+to do this can be a bit messy and errors are easily introduced so the class
+FGForce was created to provide these services in a consistent and reusable
+manner.<br><br></p>
+
+<h4>Basic usage</h4>
+
+<p>FGForce requires that its users supply it with the location of the applied
+force vector in JSBSim structural coordinates, the sense of each axis in that
+coordinate system relative to the body system, the orientation of the vector
+also relative to body coordinates and, of course, the force vector itself. With
+this information it will compute both the body axis force components and the
+resulting moments. Any moments inherently produced by the native system can be
+supplied as well and they will be summed with those computed.</p>
+
+<p>A good example for demonstrating the use of this class are the aerodynamic
+forces: lift, drag, and side force and the aerodynamic moments about the pitch,
+roll and yaw axes. These "native" forces and moments are computed and stored
+in the FGColumnVector objects vFs and vMoments. Their native coordinate system
+is often referred to as the wind system and is defined as a right-handed system
+having its x-axis aligned with the relative velocity vector and pointing towards
+the rear of the aircraft , the y-axis extending out the right wing, and the
+z-axis directed upwards. This is different than body axes; they are defined such
+that the x-axis is lies on the aircraft's roll axis and positive forward, the
+y-axis is positive out the right wing, and the z-axis is positive downwards. In
+this instance, JSBSim already provides the needed transform and FGForce can make
+use of it by calling SetTransformType() once an object is created:</p>
+
+<p><tt>FGForce fgf(FDMExec);</tt><br>
+<tt>fgf.SetTransformType(tWindBody);</tt><br><br>
+
+This call need only be made once for each object. The available transforms are
+defined in the enumerated type TransformType and are tWindBody, tLocalBody,
+tCustom, and tNone. The local-to-body transform, like the wind-to-body, also
+makes use of that already available in JSBSim. tNone sets FGForce to do no
+angular transform at all, and tCustom allows for modeling force vectors at
+arbitrary angles relative to the body system such as that produced by propulsion
+systems. Setting up and using a custom transform is covered in more detail below.
+Continuing with the example, the point of application of the aerodynamic forces,
+the aerodynamic reference point in JSBSim, also needs to be set:</p>
+<p><tt>
+fgf.SetLocation(x, y, z)</tt></p>
+
+<p>where x, y, and z are in JSBSim structural coordinates.</p>
+
+<p>Initialization is complete and the FGForce object is ready to do its job. As
+stated above, the lift, drag, and side force are computed and stored in the
+vector vFs and need to be passed to FGForce:</p>
+
+<p><tt>fgf.SetNativeForces(vFs);</tt> </p>
+
+<p>The same applies to the aerodynamic pitching, rolling and yawing moments:</p>
+
+<p><tt>fgf.SetNativeMoments(vMoments);</tt></p>
+
+<p>Note that storing the native forces and moments outside of this class is not
+strictly necessary, overloaded SetNativeForces() and SetNativeMoments() methods
+which each accept three doubles (rather than a vector) are provided and can be
+repeatedly called without incurring undue overhead. The body axes force vector
+can now be retrieved by calling:</p>
+
+<p><tt>vFb=fgf.GetBodyForces();</tt></p>
+
+<p>This method is where the bulk of the work gets done so calling it more than
+once for the same set of native forces and moments should probably be avoided.
+Note that the moment calculations are done here as well so they should not be
+retrieved after calling the GetBodyForces() method:</p>
+
+<p><tt>vM=fgf.GetMoments();</tt> </p>
+
+<p>As an aside, the native moments are not needed to perform the computations
+correctly so, if the FGForce object is not being used to store them then an
+alternate approach is to avoid the SetNativeMoments call and perform the sum</p>
+
+<p><tt>vMoments+=fgf.GetMoments();</tt> <br><br>
+
+after the forces have been retrieved. </p>
+
+<h4>Use of the Custom Transform Type</h4>
+
+<p>In cases where the native force vector is not aligned with the body, wind, or
+local coordinate systems a custom transform type is provided. A vectorable engine
+nozzle will be used to demonstrate its usage. Initialization is much the same:</p>
+
+<p><tt>FGForce fgf(FDMExec);</tt> <br>
+<tt>fgf.SetTransformType(tCustom);</tt> <br>
+<tt>fgf.SetLocation(x,y,z);</tt> </p>
+
+<p>Except that here the tCustom transform type is specified and the location of
+the thrust vector is used rather than the aerodynamic reference point. Thrust is
+typically considered to be positive when directed aft while the body x-axis is
+positive forward and, if the native system is right handed, the z-axis will be
+reversed as well. These differences in sense need to be specified using by the
+call: </p>
+
+<p><tt>fgf.SetSense(-1,1,-1);</tt></p>
+
+<p>The angles are specified by calling the method: </p>
+
+<p><tt>fgf.SetAnglesToBody(pitch, roll, yaw);</tt> </p>
+
+<p>in which the transform matrix is computed. Note that these angles should be
+taken relative to the body system and not the local as the names might suggest.
+For an aircraft with vectorable thrust, this method will need to be called
+every time the nozzle angle changes, a fixed engine/nozzle installation, on the
+other hand, will require it to be be called only once.</p>
+
+<p>Retrieval of the computed forces and moments is done as detailed above.</p>
+<br>
+<blockquote>
+    <p><i>CAVEAT: If the custom system is used to compute
+    the wind-to-body transform, then the sign of the sideslip
+    angle must be reversed when calling SetAnglesToBody().
+    This is true because sideslip angle does not follow the right
+    hand rule. Using the custom transform type this way
+    should not be necessary, as it is already provided as a built
+    in type (and the sign differences are correctly accounted for).</i>
+    <br></p>
+</blockquote>
+
+<h4>Use as a Base Type</h4>
 
-public:
+<p>For use as a base type, the native force and moment vector data members are
+defined as protected. In this case the SetNativeForces() and SetNativeMoments()
+methods need not be used and, instead, the assignments to vFn, the force vector,
+and vMn, the moments, can be made directly. Otherwise, the usage is similar.<br>
+<br><br></p>
+
+    @author Tony Peden
+    @version $Id$
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+class FGForce : public FGJSBBase
+{
+public:
+  /// Constructor
   FGForce(FGFDMExec *FDMExec);
-  ~FGForce(void);
+  /// Destructor
+  ~FGForce();
+
+  enum TransformType { tNone, tWindBody, tLocalBody, tCustom } ttype;
 
-  inline void SetNativeForces(float Fnx, float Fny, float Fnz) {
+  inline void SetNativeForces(double Fnx, double Fny, double Fnz) {
     vFn(1)=Fnx;
     vFn(2)=Fny;
     vFn(3)=Fnz;
   }
-  inline void SetNativeForces(FGColumnVector vv) { vFn = vv; };
+  inline void SetNativeForces(FGColumnVector3 vv) { vFn = vv; };
 
-  inline void SetNativeMoments(float Ln,float Mn, float Nn) {
+  inline void SetNativeMoments(double Ln,double Mn, double Nn) {
     vMn(1)=Ln;
     vMn(2)=Mn;
     vMn(3)=Nn;
   }
-  inline void SetNativeMoments(FGColumnVector vv) { vMn = vv; }
-
-  inline FGColumnVector GetNativeForces(void) { return vFn; }
-  inline FGColumnVector GetNativeMoments(void) { return vMn; }
+  inline void SetNativeMoments(FGColumnVector3 vv) { vMn = vv; }
 
+  inline FGColumnVector3& GetNativeForces(void) { return vFn; }
+  inline FGColumnVector3& GetNativeMoments(void) { return vMn; }
 
-  FGColumnVector GetBodyForces(void);
+  FGColumnVector3& GetBodyForces(void);
 
-  inline FGColumnVector GetMoments(void) { return vM; }
+  inline FGColumnVector3& GetMoments(void) { return vM; }
 
-  //point of application, JSBsim structural coords
-  //(inches, x +back, y +right, z +up)
-  inline void SetLocation(float x, float y, float z) {
-    vXYZn(1) = x;
-    vXYZn(2) = y;
-    vXYZn(3) = z;
+  // Normal point of application, JSBsim structural coords
+  // (inches, x +back, y +right, z +up)
+  inline void SetLocation(double x, double y, double z) {
+    vXYZn(eX) = x;
+    vXYZn(eY) = y;
+    vXYZn(eZ) = z;
+    SetActingLocation(x, y, z);
   }
-  inline void SetLocation(FGColumnVector vv) { vXYZn = vv; }
-  FGColumnVector GetLocation(void) { return vXYZn; }
+  
+  /** Acting point of application.
+      JSBsim structural coords used (inches, x +back, y +right, z +up).
+      This function sets the point at which the force acts - this may
+      not be the same as where the object resides. One area where this
+      is true is P-Factor modeling.
+      @param x acting location of force
+      @param y acting location of force
+      @param z acting location of force    */
+  inline void SetActingLocation(double x, double y, double z) {
+    vActingXYZn(eX) = x;
+    vActingXYZn(eY) = y;
+    vActingXYZn(eZ) = z;
+  }
+  inline void SetLocationX(double x) {vXYZn(eX) = x; vActingXYZn(eX) = x;}
+  inline void SetLocationY(double y) {vXYZn(eY) = y; vActingXYZn(eY) = y;}
+  inline void SetLocationZ(double z) {vXYZn(eZ) = z; vActingXYZn(eZ) = z;}
+  inline double SetActingLocationX(double x) {vActingXYZn(eX) = x; return x;}
+  inline double SetActingLocationY(double y) {vActingXYZn(eY) = y; return y;}
+  inline double SetActingLocationZ(double z) {vActingXYZn(eZ) = z; return z;}
+  inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; SetActingLocation(vv);}
+  inline void SetActingLocation(FGColumnVector3 vv) { vActingXYZn = vv; }
+  
+  inline double GetLocationX( void ) { return vXYZn(eX);}
+  inline double GetLocationY( void ) { return vXYZn(eY);}
+  inline double GetLocationZ( void ) { return vXYZn(eZ);}
+  inline double GetActingLocationX( void ) { return vActingXYZn(eX);}
+  inline double GetActingLocationY( void ) { return vActingXYZn(eY);}
+  inline double GetActingLocationZ( void ) { return vActingXYZn(eZ);}
+  FGColumnVector3& GetLocation(void) { return vXYZn; }
+  FGColumnVector3& GetActingLocation(void) { return vActingXYZn; }
 
   //these angles are relative to body axes, not earth!!!!!
   //I'm using these because pitch, roll, and yaw are easy to visualize,
@@ -114,35 +295,38 @@ public:
   //are going to get confused.
   //They are in radians.
 
-  void SetAnglesToBody(float broll, float bpitch, float byaw);
-  inline void  SetAnglesToBody(FGColumnVector vv) { SetAnglesToBody(vv(1), vv(2), vv(3));}
+  void SetAnglesToBody(double broll, double bpitch, double byaw);
+  inline void  SetAnglesToBody(FGColumnVector3 vv) {
+    SetAnglesToBody(vv(eRoll), vv(ePitch), vv(eYaw));
+  }
 
-  inline void SetSense(float x, float y, float z) { vSense(1)=x, vSense(2)=y, vSense(3)=z; }
-  inline void SetSense(FGColumnVector vv) { vSense=vv; }
+  inline void SetSense(double x, double y, double z) { vSense(eX)=x, vSense(eY)=y, vSense(eZ)=z; }
+  inline void SetSense(FGColumnVector3 vv) { vSense=vv; }
 
-  inline FGColumnVector GetSense(void) { return vSense; }
+  inline FGColumnVector3& GetSense(void) { return vSense; }
 
   inline void SetTransformType(TransformType ii) { ttype=ii; }
   inline TransformType GetTransformType(void) { return ttype; }
 
-  FGMatrix Transform(void);
+  FGMatrix33 Transform(void);
 
 protected:
-  FGColumnVector vFn;
-  FGColumnVector vMn;
-
+  FGFDMExec *fdmex;
+  FGColumnVector3 vFn;
+  FGColumnVector3 vMn;
+  FGColumnVector3 vH;
+  
 private:
-  FGColumnVector vFb;
-  FGColumnVector vM;
-  FGColumnVector vXYZn;
-  FGColumnVector vDXYZ;
-  FGColumnVector vSense;
+  FGColumnVector3 vFb;
+  FGColumnVector3 vM;
+  FGColumnVector3 vXYZn;
+  FGColumnVector3 vActingXYZn;
+  FGColumnVector3 vDXYZ;
+  FGColumnVector3 vSense;
 
-  FGMatrix mT;
-
-  FGFDMExec *fdmex;
-  TransformType ttype;
+  FGMatrix33 mT;
 
+  virtual void Debug(int from);
 };
 
 #endif