]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGState.cpp
Updates from the Jon and Tony show.
[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 #include "FGState.h"
51 #include "FGFDMExec.h"
52 #include "FGAtmosphere.h"
53 #include "FGFCS.h"
54 #include "FGAircraft.h"
55 #include "FGTranslation.h"
56 #include "FGRotation.h"
57 #include "FGPosition.h"
58 #include "FGAuxiliary.h"
59 #include "FGOutput.h"
60
61 /*******************************************************************************
62 ************************************ CODE **************************************
63 *******************************************************************************/
64
65
66 FGState::FGState(FGFDMExec* fdex) : mTb2l(3,3),
67     mTl2b(3,3),
68     mTs2b(3,3),
69 vQtrn(4) {
70   FDMExec = fdex;
71
72   adot = bdot = 0.0;
73   a = 1000.0;
74   sim_time = 0.0;
75   dt = 1.0/120.0;
76
77   coeffdef["FG_QBAR"]          = 1           ;
78   coeffdef["FG_WINGAREA"]      = 2           ;
79   coeffdef["FG_WINGSPAN"]      = 4           ;
80   coeffdef["FG_CBAR"]          = 8           ;
81   coeffdef["FG_ALPHA"]         = 16          ;
82   coeffdef["FG_ALPHADOT"]      = 32          ;
83   coeffdef["FG_BETA"]          = 64          ;
84   coeffdef["FG_BETADOT"]       = 128         ;
85   coeffdef["FG_PITCHRATE"]     = 256         ;
86   coeffdef["FG_ROLLRATE"]      = 512         ;
87   coeffdef["FG_YAWRATE"]       = 1024        ;
88   coeffdef["FG_MACH"]          = 2048        ;
89   coeffdef["FG_ALTITUDE"]      = 4096        ;
90   coeffdef["FG_BI2VEL"]        = 8192        ;
91   coeffdef["FG_CI2VEL"]        = 16384       ;
92   coeffdef["FG_ELEVATOR_POS"]  = 32768L      ;
93   coeffdef["FG_AILERON_POS"]   = 65536L      ;
94   coeffdef["FG_RUDDER_POS"]    = 131072L     ;
95   coeffdef["FG_SPDBRAKE_POS"]  = 262144L     ;
96   coeffdef["FG_SPOILERS_POS"]  = 524288L     ;
97   coeffdef["FG_FLAPS_POS"]     = 1048576L    ;
98   coeffdef["FG_ELEVATOR_CMD"]  = 2097152L    ;
99   coeffdef["FG_AILERON_CMD"]   = 4194304L    ;
100   coeffdef["FG_RUDDER_CMD"]    = 8388608L    ;
101   coeffdef["FG_SPDBRAKE_CMD"]  = 16777216L   ;
102   coeffdef["FG_SPOILERS_CMD"]  = 33554432L   ;
103   coeffdef["FG_FLAPS_CMD"]     = 67108864L   ;
104   coeffdef["FG_THROTTLE_CMD"]  = 134217728L  ;
105   coeffdef["FG_THROTTLE_POS"]  = 268435456L  ;
106   coeffdef["FG_HOVERB"]        = 536870912L  ;
107   coeffdef["FG_PITCH_TRIM_CMD"] = 1073741824L ;
108 }
109
110 /******************************************************************************/
111
112 FGState::~FGState(void) {}
113
114 //***************************************************************************
115 //
116 // Reset: Assume all angles READ FROM FILE IN DEGREES !!
117 //
118
119
120
121 bool FGState::Reset(string path, string acname, string fname) {
122   string resetDef;
123   float U, V, W;
124   float phi, tht, psi;
125   float latitude, longitude, h;
126
127   resetDef = path + "/" + acname + "/" + fname;
128
129   ifstream resetfile(resetDef.c_str());
130
131   if (resetfile) {
132     resetfile >> U;
133     resetfile >> V;
134     resetfile >> W;
135     resetfile >> latitude;
136     resetfile >> longitude;
137     resetfile >> phi;
138     resetfile >> tht;
139     resetfile >> psi;
140     resetfile >> h;
141     resetfile.close();
142
143     FDMExec->GetPosition()->SetLatitude(latitude*DEGTORAD);
144     FDMExec->GetPosition()->SetLongitude(longitude*DEGTORAD);
145     FDMExec->GetPosition()->Seth(h);
146
147     Initialize(U, V, W, phi*DEGTORAD, tht*DEGTORAD, psi*DEGTORAD,
148                latitude*DEGTORAD, longitude*DEGTORAD, h);
149
150     return true;
151   } else {
152     cerr << "Unable to load reset file " << fname << endl;
153     return false;
154   }
155 }
156
157 //***************************************************************************
158 //
159 // Initialize: Assume all angles GIVEN IN RADIANS !!
160 //
161
162 void FGState::Initialize(float U, float V, float W,
163                          float phi, float tht, float psi,
164                          float Latitude, float Longitude, float H) {
165   FGColumnVector vUVW(3);
166   FGColumnVector vLocalVelNED(3);
167   FGColumnVector vEuler(3);
168   float alpha, beta;
169   float qbar, Vt;
170
171   FDMExec->GetPosition()->SetLatitude(Latitude);
172   FDMExec->GetPosition()->SetLongitude(Longitude);
173   FDMExec->GetPosition()->Seth(H);
174
175   FDMExec->GetAtmosphere()->Run();
176
177   if (W != 0.0)
178     alpha = U*U > 0.0 ? atan2(W, U) : 0.0;
179   else
180     alpha = 0.0;
181   if (V != 0.0)
182     beta = U*U+W*W > 0.0 ? atan2(V, (fabs(U)/U)*sqrt(U*U + W*W)) : 0.0;
183   else
184     beta = 0.0;
185
186   vUVW << U << V << W;
187   FDMExec->GetTranslation()->SetUVW(vUVW);
188
189   vEuler << phi << tht << psi;
190   FDMExec->GetRotation()->SetEuler(vEuler);
191
192   FDMExec->GetTranslation()->SetAB(alpha, beta);
193
194   Vt = sqrt(U*U + V*V + W*W);
195   FDMExec->GetTranslation()->SetVt(Vt);
196
197   qbar = 0.5*(U*U + V*V + W*W)*FDMExec->GetAtmosphere()->GetDensity();
198   FDMExec->GetTranslation()->Setqbar(qbar);
199
200   InitMatrices(phi, tht, psi);
201
202   vLocalVelNED = mTb2l*vUVW;
203   FDMExec->GetPosition()->SetvVel(vLocalVelNED);
204 }
205
206 /******************************************************************************/
207
208 void FGState::Initialize(FGInitialCondition *FGIC) {
209
210   float tht,psi,phi;
211   float U, V, W, h;
212   float latitude, longitude;
213
214   latitude = FGIC->GetLatitudeRadIC();
215   longitude = FGIC->GetLongitudeRadIC();
216   h = FGIC->GetAltitudeFtIC();
217   U = FGIC->GetUBodyFpsIC();
218   V = FGIC->GetVBodyFpsIC();
219   W = FGIC->GetWBodyFpsIC();
220   tht = FGIC->GetThetaRadIC();
221   phi = FGIC->GetPhiRadIC();
222   psi = FGIC->GetPsiRadIC();
223
224   Initialize(U, V, W, phi, tht, psi, latitude, longitude, h);
225 }
226
227 /******************************************************************************/
228
229 bool FGState::StoreData(string fname) {
230   ofstream datafile(fname.c_str());
231
232   if (datafile) {
233     datafile << (FDMExec->GetTranslation()->GetUVW())(1);
234     datafile << (FDMExec->GetTranslation()->GetUVW())(2);
235     datafile << (FDMExec->GetTranslation()->GetUVW())(3);
236     datafile << FDMExec->GetPosition()->GetLatitude();
237     datafile << FDMExec->GetPosition()->GetLongitude();
238     datafile << (FDMExec->GetRotation()->GetEuler())(1);
239     datafile << (FDMExec->GetRotation()->GetEuler())(2);
240     datafile << (FDMExec->GetRotation()->GetEuler())(3);
241     datafile << FDMExec->GetPosition()->Geth();
242     datafile.close();
243     return true;
244   } else {
245     cerr << "Could not open dump file " << fname << endl;
246     return false;
247   }
248 }
249
250 /******************************************************************************/
251
252 float FGState::GetParameter(string val_string) {
253   return GetParameter(coeffdef[val_string]);
254 }
255
256 /******************************************************************************/
257
258 int FGState::GetParameterIndex(string val_string) {
259   return coeffdef[val_string];
260 }
261
262 /******************************************************************************/
263 //
264 // NEED WORK BELOW TO ADD NEW PARAMETERS !!!
265 //
266 float FGState::GetParameter(int val_idx) {
267   switch(val_idx) {
268   case FG_QBAR:
269     return FDMExec->GetTranslation()->Getqbar();
270   case FG_WINGAREA:
271     return FDMExec->GetAircraft()->GetWingArea();
272   case FG_WINGSPAN:
273     return FDMExec->GetAircraft()->GetWingSpan();
274   case FG_CBAR:
275     return FDMExec->GetAircraft()->Getcbar();
276   case FG_ALPHA:
277     return FDMExec->GetTranslation()->Getalpha();
278   case FG_ALPHADOT:
279     return Getadot();
280   case FG_BETA:
281     return FDMExec->GetTranslation()->Getbeta();
282   case FG_BETADOT:
283     return Getbdot();
284   case FG_PITCHRATE:
285     return (FDMExec->GetRotation()->GetPQR())(2);
286   case FG_ROLLRATE:
287     return (FDMExec->GetRotation()->GetPQR())(1);
288   case FG_YAWRATE:
289     return (FDMExec->GetRotation()->GetPQR())(3);
290   case FG_ELEVATOR_POS:
291     return FDMExec->GetFCS()->GetDePos();
292   case FG_AILERON_POS:
293     return FDMExec->GetFCS()->GetDaPos();
294   case FG_RUDDER_POS:
295     return FDMExec->GetFCS()->GetDrPos();
296   case FG_SPDBRAKE_POS:
297     return FDMExec->GetFCS()->GetDsbPos();
298   case FG_SPOILERS_POS:
299     return FDMExec->GetFCS()->GetDspPos();
300   case FG_FLAPS_POS:
301     return FDMExec->GetFCS()->GetDfPos();
302   case FG_ELEVATOR_CMD:
303     return FDMExec->GetFCS()->GetDeCmd();
304   case FG_AILERON_CMD:
305     return FDMExec->GetFCS()->GetDaCmd();
306   case FG_RUDDER_CMD:
307     return FDMExec->GetFCS()->GetDrCmd();
308   case FG_SPDBRAKE_CMD:
309     return FDMExec->GetFCS()->GetDsbCmd();
310   case FG_SPOILERS_CMD:
311     return FDMExec->GetFCS()->GetDspCmd();
312   case FG_FLAPS_CMD:
313     return FDMExec->GetFCS()->GetDfCmd();
314   case FG_MACH:
315     return FDMExec->GetTranslation()->GetMach();
316   case FG_ALTITUDE:
317     return FDMExec->GetPosition()->Geth();
318   case FG_BI2VEL:
319     return FDMExec->GetAircraft()->GetWingSpan()/(2.0 * FDMExec->GetTranslation()->GetVt());
320   case FG_CI2VEL:
321     return FDMExec->GetAircraft()->Getcbar()/(2.0 * FDMExec->GetTranslation()->GetVt());
322   case FG_THROTTLE_CMD:
323     return FDMExec->GetFCS()->GetThrottleCmd(0);
324   case FG_THROTTLE_POS:
325     return FDMExec->GetFCS()->GetThrottlePos(0);
326   case FG_HOVERB:
327     return FDMExec->GetPosition()->GetHOverB();
328   case FG_PITCH_TRIM_CMD:
329     return FDMExec->GetFCS()->GetPitchTrimCmd();
330   }
331   return 0;
332 }
333
334 /******************************************************************************/
335
336 void FGState::SetParameter(int val_idx, float val) {
337   switch(val_idx) {
338   case FG_ELEVATOR_POS:
339     FDMExec->GetFCS()->SetDePos(val);
340     break;
341   case FG_AILERON_POS:
342     FDMExec->GetFCS()->SetDaPos(val);
343     break;
344   case FG_RUDDER_POS:
345     FDMExec->GetFCS()->SetDrPos(val);
346     break;
347   case FG_SPDBRAKE_POS:
348     FDMExec->GetFCS()->SetDsbPos(val);
349     break;
350   case FG_SPOILERS_POS:
351     FDMExec->GetFCS()->SetDspPos(val);
352     break;
353   case FG_FLAPS_POS:
354     FDMExec->GetFCS()->SetDfPos(val);
355     break;
356   case FG_THROTTLE_POS:
357     FDMExec->GetFCS()->SetThrottlePos(-1,val);
358   }
359 }
360
361 /******************************************************************************/
362
363 void FGState::InitMatrices(float phi, float tht, float psi) {
364   float thtd2, psid2, phid2;
365   float Sthtd2, Spsid2, Sphid2;
366   float Cthtd2, Cpsid2, Cphid2;
367   float Cphid2Cthtd2;
368   float Cphid2Sthtd2;
369   float Sphid2Sthtd2;
370   float Sphid2Cthtd2;
371
372   thtd2 = tht/2.0;
373   psid2 = psi/2.0;
374   phid2 = phi/2.0;
375
376   Sthtd2 = sin(thtd2);
377   Spsid2 = sin(psid2);
378   Sphid2 = sin(phid2);
379
380   Cthtd2 = cos(thtd2);
381   Cpsid2 = cos(psid2);
382   Cphid2 = cos(phid2);
383
384   Cphid2Cthtd2 = Cphid2*Cthtd2;
385   Cphid2Sthtd2 = Cphid2*Sthtd2;
386   Sphid2Sthtd2 = Sphid2*Sthtd2;
387   Sphid2Cthtd2 = Sphid2*Cthtd2;
388
389   vQtrn(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2;
390   vQtrn(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2;
391   vQtrn(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2;
392   vQtrn(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2;
393
394   CalcMatrices();
395 }
396
397 /******************************************************************************/
398
399 void FGState::CalcMatrices(void) {
400   float Q0Q0, Q1Q1, Q2Q2, Q3Q3;
401   float Q0Q1, Q0Q2, Q0Q3, Q1Q2;
402   float Q1Q3, Q2Q3;
403
404   Q0Q0 = vQtrn(1)*vQtrn(1);
405   Q1Q1 = vQtrn(2)*vQtrn(2);
406   Q2Q2 = vQtrn(3)*vQtrn(3);
407   Q3Q3 = vQtrn(4)*vQtrn(4);
408   Q0Q1 = vQtrn(1)*vQtrn(2);
409   Q0Q2 = vQtrn(1)*vQtrn(3);
410   Q0Q3 = vQtrn(1)*vQtrn(4);
411   Q1Q2 = vQtrn(2)*vQtrn(3);
412   Q1Q3 = vQtrn(2)*vQtrn(4);
413   Q2Q3 = vQtrn(3)*vQtrn(4);
414
415   mTb2l(1,1) = Q0Q0 + Q1Q1 - Q2Q2 - Q3Q3;
416   mTb2l(1,2) = 2*(Q1Q2 + Q0Q3);
417   mTb2l(1,3) = 2*(Q1Q3 - Q0Q2);
418   mTb2l(2,1) = 2*(Q1Q2 - Q0Q3);
419   mTb2l(2,2) = Q0Q0 - Q1Q1 + Q2Q2 - Q3Q3;
420   mTb2l(2,3) = 2*(Q2Q3 + Q0Q1);
421   mTb2l(3,1) = 2*(Q1Q3 + Q0Q2);
422   mTb2l(3,2) = 2*(Q2Q3 - Q0Q1);
423   mTb2l(3,3) = Q0Q0 - Q1Q1 - Q2Q2 + Q3Q3;
424
425   mTl2b = mTb2l;
426   mTl2b.T();
427 }
428
429 /******************************************************************************/
430
431 void FGState::IntegrateQuat(FGColumnVector vPQR, int rate) {
432   static FGColumnVector vlastQdot(4);
433   static FGColumnVector vQdot(4);
434
435   vQdot(1) = -0.5*(vQtrn(2)*vPQR(eP) + vQtrn(3)*vPQR(eQ) + vQtrn(4)*vPQR(eR));
436   vQdot(2) =  0.5*(vQtrn(1)*vPQR(eP) + vQtrn(3)*vPQR(eR) - vQtrn(4)*vPQR(eQ));
437   vQdot(3) =  0.5*(vQtrn(1)*vPQR(eQ) + vQtrn(4)*vPQR(eP) - vQtrn(2)*vPQR(eR));
438   vQdot(4) =  0.5*(vQtrn(1)*vPQR(eR) + vQtrn(2)*vPQR(eQ) - vQtrn(3)*vPQR(eP));
439
440   vQtrn += 0.5*dt*rate*(vlastQdot + vQdot);
441
442   vQtrn.Normalize();
443
444   vlastQdot = vQdot;
445 }
446
447 /******************************************************************************/
448
449 FGColumnVector FGState::CalcEuler(void) {
450   static FGColumnVector vEuler(3);
451
452   if (mTb2l(3,3) == 0)    vEuler(ePhi) = 0.0;
453   else                    vEuler(ePhi) = atan2(mTb2l(2,3), mTb2l(3,3));
454
455   vEuler(eTht) = asin(-mTb2l(1,3));
456
457   if (mTb2l(1,1) == 0.0)  vEuler(ePsi) = 0.0;
458   else                    vEuler(ePsi) = atan2(mTb2l(1,2), mTb2l(1,1));
459
460   if (vEuler(ePsi) < 0.0) vEuler(ePsi) += 2*M_PI;
461
462   return vEuler;
463 }
464
465 /******************************************************************************/
466
467 FGMatrix FGState::GetTs2b(float alpha, float beta) {
468   float ca, cb, sa, sb;
469
470   ca = cos(alpha);
471   sa = sin(alpha);
472   cb = cos(beta);
473   sb = sin(beta);
474
475   mTs2b(1,1) = -ca*cb;
476   mTs2b(1,2) = -ca*sb;
477   mTs2b(1,3) = sa;
478   mTs2b(2,1) = -sb;
479   mTs2b(2,2) = cb;
480   mTs2b(2,3) = 0.0;
481   mTs2b(3,1) = -sa*cb;
482   mTs2b(3,2) = -sa*sb;
483   mTs2b(3,3) = -ca;
484
485   return mTs2b;
486 }
487
488 /******************************************************************************/
489