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