]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/models/propulsion/FGForce.h
0798d00e27c16184097449b2f6ef7151c318c72a
[flightgear.git] / src / FDM / JSBSim / models / propulsion / FGForce.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Header:       FGForce.h
4  Author:       Tony Peden
5  Date started: 5/20/00
6
7  ------------- Copyright (C) 1999  Anthony K. Peden (apeden@earthlink.net) -------------
8
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
17  details.
18
19  You should have received a copy of the GNU Lesser General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA  02111-1307, USA.
22
23  Further information about the GNU Lesser General Public License can also be found on
24  the world wide web at http://www.gnu.org.
25
26
27  HISTORY
28 --------------------------------------------------------------------------------
29 5/20/00  TP   Created
30
31
32 FUNCTIONAL DESCRIPTION
33 --------------------------------------------------------------------------------
34
35 The purpose of this class is to provide storage for computed forces and
36 encapsulate all the functionality associated with transforming those
37 forces from their native coord system to the body system.  This includes
38 computing the moments due to the difference between the point of application
39 and the cg.
40
41 CAVEAT:  if the custom transform is used for wind-to-body transforms then the
42          user *must* always pass this class the negative of beta. This is true
43          because sideslip angle does not follow the right hand rule i.e. it is
44          positive for aircraft nose left sideslip.  Note that use of the custom
45          transform for this purpose shouldn't be necessary as it is already
46          provided by SetTransform(tWindBody) and is not subject to the same
47          restriction.
48
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50 SENTRY
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
52
53 #ifndef FGFORCE_H
54 #define FGFORCE_H
55
56 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 INCLUDES
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59
60 #include <FGFDMExec.h>
61 #include <FGJSBBase.h>
62 #include <math/FGMatrix33.h>
63 #include <math/FGColumnVector3.h>
64
65 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66 DEFINITIONS
67 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
68
69 #define ID_FORCE "$Id$"
70
71 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 FORWARD DECLARATIONS
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
74
75 namespace JSBSim {
76
77 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 CLASS DOCUMENTATION
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
80
81 /** Utility class that aids in the conversion of forces between coordinate systems
82     and calculation of moments.
83 <br><h3>Resolution of Applied Forces into Moments and Body Axes Components</h3>
84 <br><p>
85 All forces acting on the aircraft that cannot be considered a change in weight
86 need to be resolved into body axis components so that the aircraft acceleration
87 vectors, both translational and rotational, can be computed. Furthermore, the
88 moments produced by each force that does not act at a location corresponding to
89 the center of gravity also need to be computed. Unfortunately, the math required
90 to do this can be a bit messy and errors are easily introduced so the class
91 FGForce was created to provide these services in a consistent and reusable
92 manner.<br><br></p>
93
94 <h4>Basic usage</h4>
95
96 <p>FGForce requires that its users supply it with the location of the applied
97 force vector in JSBSim structural coordinates, the sense of each axis in that
98 coordinate system relative to the body system, the orientation of the vector
99 also relative to body coordinates and, of course, the force vector itself. With
100 this information it will compute both the body axis force components and the
101 resulting moments. Any moments inherently produced by the native system can be
102 supplied as well and they will be summed with those computed.</p>
103
104 <p>A good example for demonstrating the use of this class are the aerodynamic
105 forces: lift, drag, and side force and the aerodynamic moments about the pitch,
106 roll and yaw axes. These "native" forces and moments are computed and stored
107 in the FGColumnVector objects vFs and vMoments. Their native coordinate system
108 is often referred to as the wind system and is defined as a right-handed system
109 having its x-axis aligned with the relative velocity vector and pointing towards
110 the rear of the aircraft , the y-axis extending out the right wing, and the
111 z-axis directed upwards. This is different than body axes; they are defined such
112 that the x-axis is lies on the aircraft's roll axis and positive forward, the
113 y-axis is positive out the right wing, and the z-axis is positive downwards. In
114 this instance, JSBSim already provides the needed transform and FGForce can make
115 use of it by calling SetTransformType() once an object is created:</p>
116
117 <p><tt>FGForce fgf(FDMExec);</tt><br>
118 <tt>fgf.SetTransformType(tWindBody);</tt><br><br>
119
120 This call need only be made once for each object. The available transforms are
121 defined in the enumerated type TransformType and are tWindBody, tLocalBody,
122 tCustom, and tNone. The local-to-body transform, like the wind-to-body, also
123 makes use of that already available in JSBSim. tNone sets FGForce to do no
124 angular transform at all, and tCustom allows for modeling force vectors at
125 arbitrary angles relative to the body system such as that produced by propulsion
126 systems. Setting up and using a custom transform is covered in more detail below.
127 Continuing with the example, the point of application of the aerodynamic forces,
128 the aerodynamic reference point in JSBSim, also needs to be set:</p>
129 <p><tt>
130 fgf.SetLocation(x, y, z)</tt></p>
131
132 <p>where x, y, and z are in JSBSim structural coordinates.</p>
133
134 <p>Initialization is complete and the FGForce object is ready to do its job. As
135 stated above, the lift, drag, and side force are computed and stored in the
136 vector vFs and need to be passed to FGForce:</p>
137
138 <p><tt>fgf.SetNativeForces(vFs);</tt> </p>
139
140 <p>The same applies to the aerodynamic pitching, rolling and yawing moments:</p>
141
142 <p><tt>fgf.SetNativeMoments(vMoments);</tt></p>
143
144 <p>Note that storing the native forces and moments outside of this class is not
145 strictly necessary, overloaded SetNativeForces() and SetNativeMoments() methods
146 which each accept three doubles (rather than a vector) are provided and can be
147 repeatedly called without incurring undue overhead. The body axes force vector
148 can now be retrieved by calling:</p>
149
150 <p><tt>vFb=fgf.GetBodyForces();</tt></p>
151
152 <p>This method is where the bulk of the work gets done so calling it more than
153 once for the same set of native forces and moments should probably be avoided.
154 Note that the moment calculations are done here as well so they should be
155 retrieved after calling the GetBodyForces() method:</p>
156
157 <p><tt>vM=fgf.GetMoments();</tt> </p>
158
159 <p>As an aside, the native moments are not needed to perform the computations
160 correctly so, if the FGForce object is not being used to store them then an
161 alternate approach is to avoid the SetNativeMoments call and perform the sum</p>
162
163 <p><tt>vMoments+=fgf.GetMoments();</tt> <br><br>
164
165 after the forces have been retrieved. </p>
166
167 <h4>Use of the Custom Transform Type</h4>
168
169 <p>In cases where the native force vector is not aligned with the body, wind, or
170 local coordinate systems a custom transform type is provided. A vectorable engine
171 nozzle will be used to demonstrate its usage. Initialization is much the same:</p>
172
173 <p><tt>FGForce fgf(FDMExec);</tt> <br>
174 <tt>fgf.SetTransformType(tCustom);</tt> <br>
175 <tt>fgf.SetLocation(x,y,z);</tt> </p>
176
177 <p>Except that here the tCustom transform type is specified and the location of
178 the thrust vector is used rather than the aerodynamic reference point. Thrust is
179 typically considered to be positive when directed aft while the body x-axis is
180 positive forward and, if the native system is right handed, the z-axis will be
181 reversed as well. These differences in sense need to be specified using by the
182 call: </p>
183
184 <p><tt>fgf.SetSense(-1,1,-1);</tt></p>
185
186 <p>The angles are specified by calling the method: </p>
187
188 <p><tt>fgf.SetAnglesToBody(pitch, roll, yaw);</tt> </p>
189
190 <p>in which the transform matrix is computed. Note that these angles should be
191 taken relative to the body system and not the local as the names might suggest.
192 For an aircraft with vectorable thrust, this method will need to be called
193 every time the nozzle angle changes, a fixed engine/nozzle installation, on the
194 other hand, will require it to be be called only once.</p>
195
196 <p>Retrieval of the computed forces and moments is done as detailed above.</p>
197 <br>
198 <pre>
199     <p><i>CAVEAT: If the custom system is used to compute
200     the wind-to-body transform, then the sign of the sideslip
201     angle must be reversed when calling SetAnglesToBody().
202     This is true because sideslip angle does not follow the right
203     hand rule. Using the custom transform type this way
204     should not be necessary, as it is already provided as a built
205     in type (and the sign differences are correctly accounted for).</i>
206     </p>
207 </pre>
208
209 <h4>Use as a Base Type</h4>
210
211 <p>For use as a base type, the native force and moment vector data members are
212 defined as protected. In this case the SetNativeForces() and SetNativeMoments()
213 methods need not be used and, instead, the assignments to vFn, the force vector,
214 and vMn, the moments, can be made directly. Otherwise, the usage is similar.<br>
215 <br><br></p>
216
217     @author Tony Peden
218     @version $Id$
219 */
220
221 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 CLASS DECLARATION
223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
224
225 class FGForce : public FGJSBBase
226 {
227 public:
228   /// Constructor
229   FGForce(FGFDMExec *FDMExec);
230   FGForce(const FGForce& force) {
231     vFn = force.vFn;
232     vXYZn = force.vXYZn;
233     ttype = force.ttype;
234     fdmex = force.fdmex;
235   }
236   /// Destructor
237   ~FGForce();
238
239   enum TransformType { tNone, tWindBody, tLocalBody, tCustom };
240
241   virtual FGColumnVector3& GetBodyForces(void);
242
243   inline FGColumnVector3& GetMoments(void) { return vM; }
244
245   // Normal point of application, JSBsim structural coords
246   // (inches, x +back, y +right, z +up)
247   inline void SetLocation(double x, double y, double z) {
248     vXYZn(eX) = x;
249     vXYZn(eY) = y;
250     vXYZn(eZ) = z;
251     SetActingLocation(x, y, z);
252   }
253
254   /** Acting point of application.
255       JSBsim structural coords used (inches, x +back, y +right, z +up).
256       This function sets the point at which the force acts - this may
257       not be the same as where the object resides. One area where this
258       is true is P-Factor modeling.
259       @param x acting location of force
260       @param y acting location of force
261       @param z acting location of force    */
262   inline void SetActingLocation(double x, double y, double z) {
263     vActingXYZn(eX) = x;
264     vActingXYZn(eY) = y;
265     vActingXYZn(eZ) = z;
266   }
267   inline void SetLocationX(double x) {vXYZn(eX) = x; vActingXYZn(eX) = x;}
268   inline void SetLocationY(double y) {vXYZn(eY) = y; vActingXYZn(eY) = y;}
269   inline void SetLocationZ(double z) {vXYZn(eZ) = z; vActingXYZn(eZ) = z;}
270   inline double SetActingLocationX(double x) {vActingXYZn(eX) = x; return x;}
271   inline double SetActingLocationY(double y) {vActingXYZn(eY) = y; return y;}
272   inline double SetActingLocationZ(double z) {vActingXYZn(eZ) = z; return z;}
273   inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; SetActingLocation(vv);}
274   inline void SetActingLocation(FGColumnVector3 vv) { vActingXYZn = vv; }
275
276   inline double GetLocationX( void ) { return vXYZn(eX);}
277   inline double GetLocationY( void ) { return vXYZn(eY);}
278   inline double GetLocationZ( void ) { return vXYZn(eZ);}
279   inline double GetActingLocationX( void ) { return vActingXYZn(eX);}
280   inline double GetActingLocationY( void ) { return vActingXYZn(eY);}
281   inline double GetActingLocationZ( void ) { return vActingXYZn(eZ);}
282   FGColumnVector3& GetLocation(void) { return vXYZn; }
283   FGColumnVector3& GetActingLocation(void) { return vActingXYZn; }
284
285   //these angles are relative to body axes, not earth!!!!!
286   //I'm using these because pitch, roll, and yaw are easy to visualize,
287   //there's no equivalent to roll in wind axes i.e. alpha, ? , beta
288   //making up new names or using these is a toss-up: either way people
289   //are going to get confused.
290   //They are in radians.
291
292   void SetAnglesToBody(double broll, double bpitch, double byaw);
293   inline void  SetAnglesToBody(FGColumnVector3 vv) {
294     SetAnglesToBody(vv(eRoll), vv(ePitch), vv(eYaw));
295   }
296
297   void UpdateCustomTransformMatrix(void);
298   void SetPitch(double pitch) {vOrient(ePitch) = pitch; UpdateCustomTransformMatrix();}
299   void SetYaw(double yaw) {vOrient(eYaw) = yaw; UpdateCustomTransformMatrix();}
300
301   double GetPitch(void) const {return vOrient(ePitch);}
302   double GetYaw(void) const {return vOrient(eYaw);}
303
304   inline FGColumnVector3& GetAnglesToBody(void) {return vOrient;}
305   inline double GetAnglesToBody(int axis) {return vOrient(axis);}
306
307   inline void SetTransformType(TransformType ii) { ttype=ii; }
308   inline TransformType GetTransformType(void) { return ttype; }
309
310   FGMatrix33 Transform(void);
311
312 protected:
313   FGFDMExec *fdmex;
314   FGColumnVector3 vFn;
315   FGColumnVector3 vMn;
316   FGColumnVector3 vH;
317   FGColumnVector3 vOrient;
318   TransformType ttype;
319   FGColumnVector3 vXYZn;
320   FGColumnVector3 vActingXYZn;
321
322 private:
323   FGColumnVector3 vFb;
324   FGColumnVector3 vM;
325   FGColumnVector3 vDXYZ;
326
327   FGMatrix33 mT;
328
329   void Debug(int from);
330 };
331 }
332 #endif
333