]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGRotation.cpp
Rob Deters: UIUC updates from March 1, 2004.
[flightgear.git] / src / FDM / JSBSim / FGRotation.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGRotation.cpp
4  Author:       Jon Berndt
5  Date started: 12/02/98
6  Purpose:      Integrates the rotational EOM
7  Called by:    FGFDMExec
8
9  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
10
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  details.
20
21  You should have received a copy of the GNU General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA  02111-1307, USA.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This class integrates the rotational EOM.
31
32 HISTORY
33 --------------------------------------------------------------------------------
34 12/02/98   JSB   Created
35
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 COMMENTS, REFERENCES,  and NOTES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 [1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
40     Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
41     School, January 1994
42 [2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
43     JSC 12960, July 1977
44 [3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
45     NASA-Ames", NASA CR-2497, January 1975
46 [4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
47     Wiley & Sons, 1979 ISBN 0-471-03032-5
48 [5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
49     1982 ISBN 0-471-08936-2
50
51   The order of rotations used in this class corresponds to a 3-2-1 sequence,
52   or Y-P-R, or Z-Y-X, if you prefer.
53
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 INCLUDES
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57
58 #include "FGRotation.h"
59 #include "FGAtmosphere.h"
60 #include "FGState.h"
61 #include "FGFDMExec.h"
62 #include "FGAircraft.h"
63 #include "FGMassBalance.h"
64 #include "FGPropertyManager.h"
65
66
67 namespace JSBSim {
68
69 static const char *IdSrc = "$Id$";
70 static const char *IdHdr = ID_ROTATION;
71
72 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 CLASS IMPLEMENTATION
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
75
76
77 FGRotation::FGRotation(FGFDMExec* fdmex) : FGModel(fdmex)
78 {
79   Name = "FGRotation";
80   cTht = cPhi = cPsi = 1.0;
81   sTht = sPhi = sPsi = 0.0;
82
83   vPQRdot.InitMatrix();
84   vPQRdot_prev[0].InitMatrix();
85   vPQRdot_prev[1].InitMatrix();
86   vPQRdot_prev[2].InitMatrix();
87   vPQRdot_prev[3].InitMatrix();
88
89   bind();
90
91   Debug(0);
92 }
93
94 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95
96 FGRotation::~FGRotation()
97 {
98   unbind();
99   Debug(1);
100 }
101
102 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103
104 bool FGRotation::Run(void)
105 {
106   double tTheta;
107
108   if (!FGModel::Run()) {
109     GetState();
110
111     vPQRdot = MassBalance->GetJinv()*(vMoments - vPQR*(MassBalance->GetJ()*vPQR));
112     vPQR += State->Integrate(FGState::TRAPZ, dt*rate, vPQRdot, vPQRdot_prev);
113
114     vAeroPQR = vPQR + Atmosphere->GetTurbPQR();
115
116     State->IntegrateQuat(vPQR, rate);
117     State->CalcMatrices();
118     vEuler = State->CalcEuler();
119
120     cTht = cos(vEuler(eTht));   sTht = sin(vEuler(eTht));
121     cPhi = cos(vEuler(ePhi));   sPhi = sin(vEuler(ePhi));
122     cPsi = cos(vEuler(ePsi));   sPsi = sin(vEuler(ePsi));
123
124     vEulerRates(eTht) = vPQR(2)*cPhi - vPQR(3)*sPhi;
125     if (cTht != 0.0) {
126       tTheta = sTht/cTht;       // what's cheaper: / or tan() ?
127       vEulerRates(ePhi) = vPQR(1) + (vPQR(2)*sPhi + vPQR(3)*cPhi)*tTheta;
128       vEulerRates(ePsi) = (vPQR(2)*sPhi + vPQR(3)*cPhi)/cTht;
129     }
130
131     if (debug_lvl > 1) Debug(2);
132
133     return false;
134   } else {
135     return true;
136   }
137 }
138
139 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140
141 void FGRotation::GetState(void)
142 {
143   dt = State->Getdt();
144   vMoments = Aircraft->GetMoments();
145 }
146
147 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148
149 void FGRotation::bind(void)
150 {
151   typedef double (FGRotation::*PMF)(int) const;
152   PropertyManager->Tie("velocities/p-rad_sec", this,1,
153                        (PMF)&FGRotation::GetPQR);
154   PropertyManager->Tie("velocities/q-rad_sec", this,2,
155                        (PMF)&FGRotation::GetPQR);
156   PropertyManager->Tie("velocities/r-rad_sec", this,3,
157                        (PMF)&FGRotation::GetPQR);
158   PropertyManager->Tie("velocities/p-aero-rad_sec", this,1,
159                        (PMF)&FGRotation::GetAeroPQR);
160   PropertyManager->Tie("velocities/q-aero-rad_sec", this,2,
161                        (PMF)&FGRotation::GetAeroPQR);
162   PropertyManager->Tie("velocities/r-aero-rad_sec", this,3,
163                        (PMF)&FGRotation::GetAeroPQR);
164   PropertyManager->Tie("accelerations/pdot-rad_sec", this,1,
165                        (PMF)&FGRotation::GetPQRdot);
166   PropertyManager->Tie("accelerations/qdot-rad_sec", this,2,
167                        (PMF)&FGRotation::GetPQRdot);
168   PropertyManager->Tie("accelerations/rdot-rad_sec", this,3,
169                        (PMF)&FGRotation::GetPQRdot);
170   PropertyManager->Tie("attitude/roll-rad", this,1,
171                        (PMF)&FGRotation::GetEuler);
172   PropertyManager->Tie("attitude/pitch-rad", this,2,
173                        (PMF)&FGRotation::GetEuler);
174   PropertyManager->Tie("attitude/heading-true-rad", this,3,
175                        (PMF)&FGRotation::GetEuler);
176   PropertyManager->Tie("velocities/phidot-rad_sec", this,1,
177                        (PMF)&FGRotation::GetEulerRates);
178   PropertyManager->Tie("velocities/thetadot-rad_sec", this,2,
179                        (PMF)&FGRotation::GetEulerRates);
180   PropertyManager->Tie("velocities/psidot-rad_sec", this,3,
181                        (PMF)&FGRotation::GetEulerRates);
182   PropertyManager->Tie("attitude/phi-rad", this,
183                        &FGRotation::Getphi);
184   PropertyManager->Tie("attitude/theta-rad", this,
185                        &FGRotation::Gettht);
186   PropertyManager->Tie("attitude/psi-true-rad", this,
187                        &FGRotation::Getpsi);
188 }
189
190 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191
192 void FGRotation::unbind(void)
193 {
194   PropertyManager->Untie("velocities/p-rad_sec");
195   PropertyManager->Untie("velocities/q-rad_sec");
196   PropertyManager->Untie("velocities/r-rad_sec");
197   PropertyManager->Untie("velocities/p-aero-rad_sec");
198   PropertyManager->Untie("velocities/q-aero-rad_sec");
199   PropertyManager->Untie("velocities/r-aero-rad_sec");
200   PropertyManager->Untie("accelerations/pdot-rad_sec");
201   PropertyManager->Untie("accelerations/qdot-rad_sec");
202   PropertyManager->Untie("accelerations/rdot-rad_sec");
203   PropertyManager->Untie("attitude/roll-rad");
204   PropertyManager->Untie("attitude/pitch-rad");
205   PropertyManager->Untie("attitude/heading-true-rad");
206   PropertyManager->Untie("velocities/phidot-rad_sec");
207   PropertyManager->Untie("velocities/thetadot-rad_sec");
208   PropertyManager->Untie("velocities/psidot-rad_sec");
209   PropertyManager->Untie("attitude/phi-rad");
210   PropertyManager->Untie("attitude/theta-rad");
211   PropertyManager->Untie("attitude/psi-true-rad");
212 }
213
214 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 //    The bitmasked value choices are as follows:
216 //    unset: In this case (the default) JSBSim would only print
217 //       out the normally expected messages, essentially echoing
218 //       the config files as they are read. If the environment
219 //       variable is not set, debug_lvl is set to 1 internally
220 //    0: This requests JSBSim not to output any messages
221 //       whatsoever.
222 //    1: This value explicity requests the normal JSBSim
223 //       startup messages
224 //    2: This value asks for a message to be printed out when
225 //       a class is instantiated
226 //    4: When this value is set, a message is displayed when a
227 //       FGModel object executes its Run() method
228 //    8: When this value is set, various runtime state variables
229 //       are printed out periodically
230 //    16: When set various parameters are sanity checked and
231 //       a message is printed out when they go out of bounds
232
233 void FGRotation::Debug(int from)
234 {
235   if (debug_lvl <= 0) return;
236
237   if (debug_lvl & 1) { // Standard console startup message output
238     if (from == 0) { // Constructor
239
240     }
241   }
242   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
243     if (from == 0) cout << "Instantiated: FGRotation" << endl;
244     if (from == 1) cout << "Destroyed:    FGRotation" << endl;
245   }
246   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
247   }
248   if (debug_lvl & 8 ) { // Runtime state variables
249   }
250   if (debug_lvl & 16) { // Sanity check variables
251     if (from == 2) {
252       if (fabs(vPQR(eP)) > 100)
253         cout << "FGRotation::P (Roll Rate) out of bounds: " << vPQR(eP) << endl;
254       if (fabs(vPQR(eQ)) > 100)
255         cout << "FGRotation::Q (Pitch Rate) out of bounds: " << vPQR(eQ) << endl;
256       if (fabs(vPQR(eR)) > 100)
257         cout << "FGRotation::R (Yaw Rate) out of bounds: " << vPQR(eR) << endl;
258     }
259   }
260   if (debug_lvl & 64) {
261     if (from == 0) { // Constructor
262       cout << IdSrc << endl;
263       cout << IdHdr << endl;
264     }
265   }
266 }
267 }