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