Branch data Line data Source code
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: FGForce.h,v 1.13 2009/10/05 04:48:03 jberndt Exp $"
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: FGForce.h,v 1.13 2009/10/05 04:48:03 jberndt Exp $
219 : : */
220 : :
221 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 : : CLASS DECLARATION
223 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
224 : :
225 : : class FGForce : public FGJSBBase
226 : : {
227 : : public:
228 : : /// Constructor
229 : : FGForce(FGFDMExec *FDMExec);
230 : 0 : FGForce(const FGForce& force) {
231 : 0 : vFn = force.vFn;
232 : 0 : vXYZn = force.vXYZn;
233 : 0 : ttype = force.ttype;
234 : 0 : fdmex = force.fdmex;
235 : 0 : }
236 : : /// Destructor
237 : : ~FGForce();
238 : :
239 : : enum TransformType { tNone, tWindBody, tLocalBody, tCustom };
240 : :
241 : : virtual FGColumnVector3& GetBodyForces(void);
242 : :
243 : 0 : inline double GetBodyXForce(void) const { return vFb(eX); }
244 : 0 : inline double GetBodyYForce(void) const { return vFb(eY); }
245 : : inline double GetBodyZForce(void) const { return vFb(eZ); }
246 : 648060 : inline FGColumnVector3& GetMoments(void) { return vM; }
247 : :
248 : : // Normal point of application, JSBsim structural coords
249 : : // (inches, x +back, y +right, z +up)
250 : : inline void SetLocation(double x, double y, double z) {
251 : : vXYZn(eX) = x;
252 : : vXYZn(eY) = y;
253 : : vXYZn(eZ) = z;
254 : : SetActingLocation(x, y, z);
255 : : }
256 : :
257 : : /** Acting point of application.
258 : : JSBsim structural coords used (inches, x +back, y +right, z +up).
259 : : This function sets the point at which the force acts - this may
260 : : not be the same as where the object resides. One area where this
261 : : is true is P-Factor modeling.
262 : : @param x acting location of force
263 : : @param y acting location of force
264 : : @param z acting location of force */
265 : : inline void SetActingLocation(double x, double y, double z) {
266 : : vActingXYZn(eX) = x;
267 : : vActingXYZn(eY) = y;
268 : : vActingXYZn(eZ) = z;
269 : : }
270 : : inline void SetLocationX(double x) {vXYZn(eX) = x; vActingXYZn(eX) = x;}
271 : : inline void SetLocationY(double y) {vXYZn(eY) = y; vActingXYZn(eY) = y;}
272 : 0 : inline void SetLocationZ(double z) {vXYZn(eZ) = z; vActingXYZn(eZ) = z;}
273 : : inline double SetActingLocationX(double x) {vActingXYZn(eX) = x; return x;}
274 : 0 : inline double SetActingLocationY(double y) {vActingXYZn(eY) = y; return y;}
275 : 0 : inline double SetActingLocationZ(double z) {vActingXYZn(eZ) = z; return z;}
276 : 12 : inline void SetLocation(FGColumnVector3 vv) { vXYZn = vv; SetActingLocation(vv);}
277 : 12 : inline void SetActingLocation(FGColumnVector3 vv) { vActingXYZn = vv; }
278 : :
279 : 24 : inline double GetLocationX( void ) const { return vXYZn(eX);}
280 : 24 : inline double GetLocationY( void ) const { return vXYZn(eY);}
281 : 24 : inline double GetLocationZ( void ) const { return vXYZn(eZ);}
282 : : inline double GetActingLocationX( void ) const { return vActingXYZn(eX);}
283 : 0 : inline double GetActingLocationY( void ) const { return vActingXYZn(eY);}
284 : 0 : inline double GetActingLocationZ( void ) const { return vActingXYZn(eZ);}
285 : : FGColumnVector3& GetLocation(void) { return vXYZn; }
286 : : FGColumnVector3& GetActingLocation(void) { return vActingXYZn; }
287 : :
288 : : //these angles are relative to body axes, not earth!!!!!
289 : : //I'm using these because pitch, roll, and yaw are easy to visualize,
290 : : //there's no equivalent to roll in wind axes i.e. alpha, ? , beta
291 : : //making up new names or using these is a toss-up: either way people
292 : : //are going to get confused.
293 : : //They are in radians.
294 : :
295 : : void SetAnglesToBody(double broll, double bpitch, double byaw);
296 : : inline void SetAnglesToBody(FGColumnVector3 vv) {
297 : 12 : SetAnglesToBody(vv(eRoll), vv(ePitch), vv(eYaw));
298 : : }
299 : :
300 : : void UpdateCustomTransformMatrix(void);
301 : 324030 : void SetPitch(double pitch) {vOrient(ePitch) = pitch; UpdateCustomTransformMatrix();}
302 : 324030 : void SetYaw(double yaw) {vOrient(eYaw) = yaw; UpdateCustomTransformMatrix();}
303 : :
304 : 12 : double GetPitch(void) const {return vOrient(ePitch);}
305 : 12 : double GetYaw(void) const {return vOrient(eYaw);}
306 : :
307 : : inline FGColumnVector3& GetAnglesToBody(void) {return vOrient;}
308 : 48 : inline double GetAnglesToBody(int axis) const {return vOrient(axis);}
309 : :
310 : 12 : inline void SetTransformType(TransformType ii) { ttype=ii; }
311 : : inline TransformType GetTransformType(void) const { return ttype; }
312 : :
313 : : FGMatrix33 Transform(void);
314 : :
315 : : protected:
316 : : FGFDMExec *fdmex;
317 : : FGColumnVector3 vFn;
318 : : FGColumnVector3 vMn;
319 : : FGColumnVector3 vH;
320 : : FGColumnVector3 vOrient;
321 : : TransformType ttype;
322 : : FGColumnVector3 vXYZn;
323 : : FGColumnVector3 vActingXYZn;
324 : :
325 : : private:
326 : : FGColumnVector3 vFb;
327 : : FGColumnVector3 vM;
328 : : FGColumnVector3 vDXYZ;
329 : :
330 : : FGMatrix33 mT;
331 : :
332 : : void Debug(int from);
333 : : };
334 : : }
335 : : #endif
336 : :
|