]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGState.cpp
builddir -> srcdir so builds can be done outside the master source directory.
[flightgear.git] / src / FDM / JSBSim / FGState.cpp
1 /*******************************************************************************
2                                                                        
3  Module:       FGState.cpp
4  Author:       Jon Berndt
5  Date started: 11/17/98
6  Called by:    FGFDMExec and accessed by all models.
7  
8  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
9  
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14  
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19  
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23  
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26  
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29 See header file.
30  
31 HISTORY
32 --------------------------------------------------------------------------------
33 11/17/98   JSB   Created
34  
35 ********************************************************************************
36 INCLUDES
37 *******************************************************************************/
38
39 #ifdef FGFS
40 #  include <simgear/compiler.h>
41 #  ifdef FG_HAVE_STD_INCLUDES
42 #    include <cmath>
43 #  else
44 #    include <math.h>
45 #  endif
46 #else
47 #  include <cmath>
48 #endif
49
50 #ifndef M_PI         // support for silly Microsoft compiler
51 #  include <simgear/constants.h>
52 #  define M_PI FG_PI
53 #endif 
54
55 #include "FGState.h"
56 #include "FGFDMExec.h"
57 #include "FGAtmosphere.h"
58 #include "FGFCS.h"
59 #include "FGAircraft.h"
60 #include "FGTranslation.h"
61 #include "FGRotation.h"
62 #include "FGPosition.h"
63 #include "FGAuxiliary.h"
64 #include "FGOutput.h"
65
66 /*******************************************************************************
67 ************************************ CODE **************************************
68 *******************************************************************************/
69
70
71 FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3),
72     mTl2b(3,3),
73     mTs2b(3,3),
74     vQtrn(4)
75 {
76   FDMExec = fdex;
77
78   adot = bdot = 0.0;
79   a = 1000.0;
80   sim_time = 0.0;
81   dt = 1.0/120.0;
82
83   coeffdef["FG_QBAR"]          = 1           ;
84   coeffdef["FG_WINGAREA"]      = 2           ;
85   coeffdef["FG_WINGSPAN"]      = 4           ;
86   coeffdef["FG_CBAR"]          = 8           ;
87   coeffdef["FG_ALPHA"]         = 16          ;
88   coeffdef["FG_ALPHADOT"]      = 32          ;
89   coeffdef["FG_BETA"]          = 64          ;
90   coeffdef["FG_BETADOT"]       = 128         ;
91   coeffdef["FG_PITCHRATE"]     = 256         ;
92   coeffdef["FG_ROLLRATE"]      = 512         ;
93   coeffdef["FG_YAWRATE"]       = 1024        ;
94   coeffdef["FG_MACH"]          = 2048        ;
95   coeffdef["FG_ALTITUDE"]      = 4096        ;
96   coeffdef["FG_BI2VEL"]        = 8192        ;
97   coeffdef["FG_CI2VEL"]        = 16384       ;
98   coeffdef["FG_ELEVATOR_POS"]  = 32768L      ;
99   coeffdef["FG_AILERON_POS"]   = 65536L      ;
100   coeffdef["FG_RUDDER_POS"]    = 131072L     ;
101   coeffdef["FG_SPDBRAKE_POS"]  = 262144L     ;
102   coeffdef["FG_SPOILERS_POS"]  = 524288L     ;
103   coeffdef["FG_FLAPS_POS"]     = 1048576L    ;
104   coeffdef["FG_ELEVATOR_CMD"]  = 2097152L    ;
105   coeffdef["FG_AILERON_CMD"]   = 4194304L    ;
106   coeffdef["FG_RUDDER_CMD"]    = 8388608L    ;
107   coeffdef["FG_SPDBRAKE_CMD"]  = 16777216L   ;
108   coeffdef["FG_SPOILERS_CMD"]  = 33554432L   ;
109   coeffdef["FG_FLAPS_CMD"]     = 67108864L   ;
110   coeffdef["FG_THROTTLE_CMD"]  = 134217728L  ;
111   coeffdef["FG_THROTTLE_POS"]  = 268435456L  ;
112   coeffdef["FG_HOVERB"]        = 536870912L  ;
113   coeffdef["FG_PITCH_TRIM_CMD"] = 1073741824L ;
114 }
115
116 /******************************************************************************/
117
118 FGState::~FGState(void) {}
119
120 //***************************************************************************
121 //
122 // Reset: Assume all angles READ FROM FILE IN DEGREES !!
123 //
124
125
126
127 bool FGState::Reset(string path, string acname, string fname) {
128   string resetDef;
129   float U, V, W;
130   float phi, tht, psi;
131   float latitude, longitude, h;
132
133   resetDef = path + "/" + acname + "/" + fname;
134
135   ifstream resetfile(resetDef.c_str());
136
137   if (resetfile) {
138     resetfile >> U;
139     resetfile >> V;
140     resetfile >> W;
141     resetfile >> latitude;
142     resetfile >> longitude;
143     resetfile >> phi;
144     resetfile >> tht;
145     resetfile >> psi;
146     resetfile >> h;
147     resetfile.close();
148
149     FDMExec->GetPosition()->SetLatitude(latitude*DEGTORAD);
150     FDMExec->GetPosition()->SetLongitude(longitude*DEGTORAD);
151     FDMExec->GetPosition()->Seth(h);
152
153     Initialize(U, V, W, phi*DEGTORAD, tht*DEGTORAD, psi*DEGTORAD,
154                latitude*DEGTORAD, longitude*DEGTORAD, h);
155
156     return true;
157   } else {
158     cerr << "Unable to load reset file " << fname << endl;
159     return false;
160   }
161 }
162
163 //***************************************************************************
164 //
165 // Initialize: Assume all angles GIVEN IN RADIANS !!
166 //
167
168 void FGState::Initialize(float U, float V, float W,
169                          float phi, float tht, float psi,
170                          float Latitude, float Longitude, float H) {
171   FGColumnVector vUVW(3);
172   FGColumnVector vLocalVelNED(3);
173   FGColumnVector vEuler(3);
174   float alpha, beta;
175   float qbar, Vt;
176
177   FDMExec->GetPosition()->SetLatitude(Latitude);
178   FDMExec->GetPosition()->SetLongitude(Longitude);
179   FDMExec->GetPosition()->Seth(H);
180
181   FDMExec->GetAtmosphere()->Run();
182
183   if (W != 0.0)
184     alpha = U*U > 0.0 ? atan2(W, U) : 0.0;
185   else
186     alpha = 0.0;
187   if (V != 0.0)
188     beta = U*U+W*W > 0.0 ? atan2(V, (fabs(U)/U)*sqrt(U*U + W*W)) : 0.0;
189   else
190     beta = 0.0;
191
192   vUVW << U << V << W;
193   FDMExec->GetTranslation()->SetUVW(vUVW);
194
195   vEuler << phi << tht << psi;
196   FDMExec->GetRotation()->SetEuler(vEuler);
197
198   FDMExec->GetTranslation()->SetAB(alpha, beta);
199
200   Vt = sqrt(U*U + V*V + W*W);
201   FDMExec->GetTranslation()->SetVt(Vt);
202
203   qbar = 0.5*(U*U + V*V + W*W)*FDMExec->GetAtmosphere()->GetDensity();
204   FDMExec->GetTranslation()->Setqbar(qbar);
205
206   InitMatrices(phi, tht, psi);
207
208   vLocalVelNED = mTb2l*vUVW;
209   FDMExec->GetPosition()->SetvVel(vLocalVelNED);
210 }
211
212 /******************************************************************************/
213
214 void FGState::Initialize(FGInitialCondition *FGIC) {
215
216   float tht,psi,phi;
217   float U, V, W, h;
218   float latitude, longitude;
219
220   latitude = FGIC->GetLatitudeRadIC();
221   longitude = FGIC->GetLongitudeRadIC();
222   h = FGIC->GetAltitudeFtIC();
223   U = FGIC->GetUBodyFpsIC();
224   V = FGIC->GetVBodyFpsIC();
225   W = FGIC->GetWBodyFpsIC();
226   tht = FGIC->GetThetaRadIC();
227   phi = FGIC->GetPhiRadIC();
228   psi = FGIC->GetPsiRadIC();
229
230   Initialize(U, V, W, phi, tht, psi, latitude, longitude, h);
231 }
232
233 /******************************************************************************/
234
235 bool FGState::StoreData(string fname) {
236   ofstream datafile(fname.c_str());
237
238   if (datafile) {
239     datafile << (FDMExec->GetTranslation()->GetUVW())(1);
240     datafile << (FDMExec->GetTranslation()->GetUVW())(2);
241     datafile << (FDMExec->GetTranslation()->GetUVW())(3);
242     datafile << FDMExec->GetPosition()->GetLatitude();
243     datafile << FDMExec->GetPosition()->GetLongitude();
244     datafile << (FDMExec->GetRotation()->GetEuler())(1);
245     datafile << (FDMExec->GetRotation()->GetEuler())(2);
246     datafile << (FDMExec->GetRotation()->GetEuler())(3);
247     datafile << FDMExec->GetPosition()->Geth();
248     datafile.close();
249     return true;
250   } else {
251     cerr << "Could not open dump file " << fname << endl;
252     return false;
253   }
254 }
255
256 /******************************************************************************/
257
258 float FGState::GetParameter(string val_string) {
259   return GetParameter(coeffdef[val_string]);
260 }
261
262 /******************************************************************************/
263
264 int FGState::GetParameterIndex(string val_string) {
265   return coeffdef[val_string];
266 }
267
268 /******************************************************************************/
269 //
270 // NEED WORK BELOW TO ADD NEW PARAMETERS !!!
271 //
272 float FGState::GetParameter(int val_idx) {
273   switch(val_idx) {
274   case FG_QBAR:
275     return FDMExec->GetTranslation()->Getqbar();
276   case FG_WINGAREA:
277     return FDMExec->GetAircraft()->GetWingArea();
278   case FG_WINGSPAN:
279     return FDMExec->GetAircraft()->GetWingSpan();
280   case FG_CBAR:
281     return FDMExec->GetAircraft()->Getcbar();
282   case FG_ALPHA:
283     return FDMExec->GetTranslation()->Getalpha();
284   case FG_ALPHADOT:
285     return Getadot();
286   case FG_BETA:
287     return FDMExec->GetTranslation()->Getbeta();
288   case FG_BETADOT:
289     return Getbdot();
290   case FG_PITCHRATE:
291     return (FDMExec->GetRotation()->GetPQR())(2);
292   case FG_ROLLRATE:
293     return (FDMExec->GetRotation()->GetPQR())(1);
294   case FG_YAWRATE:
295     return (FDMExec->GetRotation()->GetPQR())(3);
296   case FG_ELEVATOR_POS:
297     return FDMExec->GetFCS()->GetDePos();
298   case FG_AILERON_POS:
299     return FDMExec->GetFCS()->GetDaPos();
300   case FG_RUDDER_POS:
301     return FDMExec->GetFCS()->GetDrPos();
302   case FG_SPDBRAKE_POS:
303     return FDMExec->GetFCS()->GetDsbPos();
304   case FG_SPOILERS_POS:
305     return FDMExec->GetFCS()->GetDspPos();
306   case FG_FLAPS_POS:
307     return FDMExec->GetFCS()->GetDfPos();
308   case FG_ELEVATOR_CMD:
309     return FDMExec->GetFCS()->GetDeCmd();
310   case FG_AILERON_CMD:
311     return FDMExec->GetFCS()->GetDaCmd();
312   case FG_RUDDER_CMD:
313     return FDMExec->GetFCS()->GetDrCmd();
314   case FG_SPDBRAKE_CMD:
315     return FDMExec->GetFCS()->GetDsbCmd();
316   case FG_SPOILERS_CMD:
317     return FDMExec->GetFCS()->GetDspCmd();
318   case FG_FLAPS_CMD:
319     return FDMExec->GetFCS()->GetDfCmd();
320   case FG_MACH:
321     return FDMExec->GetTranslation()->GetMach();
322   case FG_ALTITUDE:
323     return FDMExec->GetPosition()->Geth();
324   case FG_BI2VEL:
325     if(FDMExec->GetTranslation()->GetVt() > 0)
326         return FDMExec->GetAircraft()->GetWingSpan()/(2.0 * FDMExec->GetTranslation()->GetVt());
327     else
328         return 0;
329   case FG_CI2VEL:
330     if(FDMExec->GetTranslation()->GetVt() > 0)
331         return FDMExec->GetAircraft()->Getcbar()/(2.0 * FDMExec->GetTranslation()->GetVt());
332     else
333         return 0;
334   case FG_THROTTLE_CMD:
335     return FDMExec->GetFCS()->GetThrottleCmd(0);
336   case FG_THROTTLE_POS:
337     return FDMExec->GetFCS()->GetThrottlePos(0);
338   case FG_HOVERB:
339     return FDMExec->GetPosition()->GetHOverB();
340   case FG_PITCH_TRIM_CMD:
341     return FDMExec->GetFCS()->GetPitchTrimCmd();
342   }
343   return 0;
344 }
345
346 /******************************************************************************/
347
348 void FGState::SetParameter(int val_idx, float val) {
349   switch(val_idx) {
350   case FG_ELEVATOR_POS:
351     FDMExec->GetFCS()->SetDePos(val);
352     break;
353   case FG_AILERON_POS:
354     FDMExec->GetFCS()->SetDaPos(val);
355     break;
356   case FG_RUDDER_POS:
357     FDMExec->GetFCS()->SetDrPos(val);
358     break;
359   case FG_SPDBRAKE_POS:
360     FDMExec->GetFCS()->SetDsbPos(val);
361     break;
362   case FG_SPOILERS_POS:
363     FDMExec->GetFCS()->SetDspPos(val);
364     break;
365   case FG_FLAPS_POS:
366     FDMExec->GetFCS()->SetDfPos(val);
367     break;
368   case FG_THROTTLE_POS:
369     FDMExec->GetFCS()->SetThrottlePos(-1,val);
370   }
371 }
372
373 /******************************************************************************/
374
375 void FGState::InitMatrices(float phi, float tht, float psi) {
376   float thtd2, psid2, phid2;
377   float Sthtd2, Spsid2, Sphid2;
378   float Cthtd2, Cpsid2, Cphid2;
379   float Cphid2Cthtd2;
380   float Cphid2Sthtd2;
381   float Sphid2Sthtd2;
382   float Sphid2Cthtd2;
383
384   thtd2 = tht/2.0;
385   psid2 = psi/2.0;
386   phid2 = phi/2.0;
387
388   Sthtd2 = sin(thtd2);
389   Spsid2 = sin(psid2);
390   Sphid2 = sin(phid2);
391
392   Cthtd2 = cos(thtd2);
393   Cpsid2 = cos(psid2);
394   Cphid2 = cos(phid2);
395
396   Cphid2Cthtd2 = Cphid2*Cthtd2;
397   Cphid2Sthtd2 = Cphid2*Sthtd2;
398   Sphid2Sthtd2 = Sphid2*Sthtd2;
399   Sphid2Cthtd2 = Sphid2*Cthtd2;
400
401   vQtrn(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2;
402   vQtrn(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2;
403   vQtrn(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2;
404   vQtrn(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2;
405
406   CalcMatrices();
407 }
408
409 /******************************************************************************/
410
411 void FGState::CalcMatrices(void) {
412   float Q0Q0, Q1Q1, Q2Q2, Q3Q3;
413   float Q0Q1, Q0Q2, Q0Q3, Q1Q2;
414   float Q1Q3, Q2Q3;
415
416   Q0Q0 = vQtrn(1)*vQtrn(1);
417   Q1Q1 = vQtrn(2)*vQtrn(2);
418   Q2Q2 = vQtrn(3)*vQtrn(3);
419   Q3Q3 = vQtrn(4)*vQtrn(4);
420   Q0Q1 = vQtrn(1)*vQtrn(2);
421   Q0Q2 = vQtrn(1)*vQtrn(3);
422   Q0Q3 = vQtrn(1)*vQtrn(4);
423   Q1Q2 = vQtrn(2)*vQtrn(3);
424   Q1Q3 = vQtrn(2)*vQtrn(4);
425   Q2Q3 = vQtrn(3)*vQtrn(4);
426
427   mTl2b(1,1) = Q0Q0 + Q1Q1 - Q2Q2 - Q3Q3;
428   mTl2b(1,2) = 2*(Q1Q2 + Q0Q3);
429   mTl2b(1,3) = 2*(Q1Q3 - Q0Q2);
430   mTl2b(2,1) = 2*(Q1Q2 - Q0Q3);
431   mTl2b(2,2) = Q0Q0 - Q1Q1 + Q2Q2 - Q3Q3;
432   mTl2b(2,3) = 2*(Q2Q3 + Q0Q1);
433   mTl2b(3,1) = 2*(Q1Q3 + Q0Q2);
434   mTl2b(3,2) = 2*(Q2Q3 - Q0Q1);
435   mTl2b(3,3) = Q0Q0 - Q1Q1 - Q2Q2 + Q3Q3;
436
437   mTb2l = mTl2b;
438   mTb2l.T();
439 }
440
441 /******************************************************************************/
442
443 void FGState::IntegrateQuat(FGColumnVector vPQR, int rate) {
444   static FGColumnVector vlastQdot(4);
445   static FGColumnVector vQdot(4);
446
447   vQdot(1) = -0.5*(vQtrn(2)*vPQR(eP) + vQtrn(3)*vPQR(eQ) + vQtrn(4)*vPQR(eR));
448   vQdot(2) =  0.5*(vQtrn(1)*vPQR(eP) + vQtrn(3)*vPQR(eR) - vQtrn(4)*vPQR(eQ));
449   vQdot(3) =  0.5*(vQtrn(1)*vPQR(eQ) + vQtrn(4)*vPQR(eP) - vQtrn(2)*vPQR(eR));
450   vQdot(4) =  0.5*(vQtrn(1)*vPQR(eR) + vQtrn(2)*vPQR(eQ) - vQtrn(3)*vPQR(eP));
451
452   vQtrn += 0.5*dt*rate*(vlastQdot + vQdot);
453
454   vQtrn.Normalize();
455
456   vlastQdot = vQdot;
457 }
458
459 /******************************************************************************/
460
461 FGColumnVector FGState::CalcEuler(void) {
462   static FGColumnVector vEuler(3);
463
464   if (mTl2b(3,3) == 0.0) mTl2b(3,3) = 0.0000001;
465   if (mTl2b(1,1) == 0.0) mTl2b(1,1) = 0.0000001;
466
467   vEuler(ePhi) = atan2(mTl2b(2,3), mTl2b(3,3));
468   vEuler(eTht) = asin(-mTl2b(1,3));
469   vEuler(ePsi) = atan2(mTl2b(1,2), mTl2b(1,1));
470
471   if (vEuler(ePsi) < 0.0) vEuler(ePsi) += 2*M_PI;
472
473   return vEuler;
474 }
475
476 /******************************************************************************/
477
478 FGMatrix FGState::GetTs2b(float alpha, float beta) {
479   float ca, cb, sa, sb;
480
481   ca = cos(alpha);
482   sa = sin(alpha);
483   cb = cos(beta);
484   sb = sin(beta);
485
486   mTs2b(1,1) = -ca*cb;
487   mTs2b(1,2) = -ca*sb;
488   mTs2b(1,3) = sa;
489   mTs2b(2,1) = -sb;
490   mTs2b(2,2) = cb;
491   mTs2b(2,3) = 0.0;
492   mTs2b(3,1) = -sa*cb;
493   mTs2b(3,2) = -sa*sb;
494   mTs2b(3,3) = -ca;
495
496   return mTs2b;
497 }
498
499 /******************************************************************************/
500