]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGAerodynamics.cpp
Typo
[flightgear.git] / src / FDM / JSBSim / FGAerodynamics.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGAerodynamics.cpp
4  Author:       Jon S. Berndt
5  Date started: 09/13/00
6  Purpose:      Encapsulates the aerodynamic forces (gear and collision)
7
8  ------------- Copyright (C) 2000  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
30 HISTORY
31 --------------------------------------------------------------------------------
32 09/13/00   JSB   Created
33 04/22/01   JSB   Moved code into here from FGAircraft
34
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 INCLUDES
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38
39 #ifdef HAVE_CONFIG_H
40 #  include <config.h>
41 #endif
42
43 #include "FGAerodynamics.h"
44 #include "FGPropagate.h"
45 #include "FGAircraft.h"
46 #include "FGState.h"
47 #include "FGMassBalance.h"
48 #include "FGFactorGroup.h"
49 #include "FGPropertyManager.h"
50
51 namespace JSBSim {
52
53 static const char *IdSrc = "$Id$";
54 static const char *IdHdr = ID_AERODYNAMICS;
55
56 const unsigned NAxes=6;
57 const char* AxisNames[] = { "drag", "side", "lift", "roll",
58                             "pitch","yaw" };
59 const char* AxisNamesUpper[] = { "DRAG", "SIDE", "LIFT", "ROLL",
60                                  "PITCH","YAW" };
61
62 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 CLASS IMPLEMENTATION
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
65
66
67 FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
68 {
69   Name = "FGAerodynamics";
70
71   AxisIdx["DRAG"]  = 0;
72   AxisIdx["SIDE"]  = 1;
73   AxisIdx["LIFT"]  = 2;
74   AxisIdx["ROLL"]  = 3;
75   AxisIdx["PITCH"] = 4;
76   AxisIdx["YAW"]   = 5;
77
78   Coeff = new CoeffArray[6];
79
80   impending_stall = stall_hyst = 0.0;
81   alphaclmin = alphaclmax = 0.0;
82   alphahystmin = alphahystmax = 0.0;
83   clsq = lod = 0.0;
84   alphaw = 0.0;
85   bi2vel = ci2vel = 0.0;
86   bind();
87
88   Debug(0);
89 }
90
91 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92
93 FGAerodynamics::~FGAerodynamics()
94 {
95   unsigned int i,j;
96
97   unbind();
98
99   for (i=0; i<6; i++) {
100     for (j=0; j<Coeff[i].size(); j++) {
101       delete Coeff[i][j];
102     }
103   }
104   delete[] Coeff;
105
106   Debug(1);
107 }
108
109 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110
111 bool FGAerodynamics::Run(void)
112 {
113   unsigned int axis_ctr,ctr;
114   double alpha, twovel;
115
116   if (!FGModel::Run()) {
117
118     twovel = 2*Auxiliary->GetVt();
119     if (twovel != 0) {
120       bi2vel = Aircraft->GetWingSpan() / twovel;
121       ci2vel = Aircraft->Getcbar() / twovel;
122     }
123
124     alphaw = Auxiliary->Getalpha() + Aircraft->GetWingIncidence();
125
126     alpha = Auxiliary->Getalpha();
127
128     if (alphaclmax != 0) {
129       if (alpha > 0.85*alphaclmax) {
130         impending_stall = 10*(alpha/alphaclmax - 0.85);
131       } else {
132         impending_stall = 0;
133       }
134     }
135
136     if (alphahystmax != 0.0 && alphahystmin != 0.0) {
137       if (alpha > alphahystmax) {
138          stall_hyst = 1;
139       } else if (alpha < alphahystmin) {
140          stall_hyst = 0;
141       }
142     }
143
144     vLastFs = vFs;
145     vFs.InitMatrix();
146
147     for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
148       for (ctr=0; ctr < Coeff[axis_ctr].size(); ctr++) {
149         vFs(axis_ctr+1) += Coeff[axis_ctr][ctr]->TotalValue();
150       }
151     }
152
153     //correct signs of drag and lift to wind axes convention
154     //positive forward, right, down
155     if ( Auxiliary->Getqbar() > 0) {
156       clsq = vFs(eLift) / (Aircraft->GetWingArea()*Auxiliary->Getqbar());
157       clsq *= clsq;
158     }
159     if ( vFs(eDrag)  > 0) {
160       lod = vFs(eLift) / vFs(eDrag);
161     }
162
163     //correct signs of drag and lift to wind axes convention
164     //positive forward, right, down
165     vFs(eDrag)*=-1; vFs(eLift)*=-1;
166
167     vForces = State->GetTs2b()*vFs;
168
169     vDXYZcg = MassBalance->StructuralToBody(Aircraft->GetXYZrp());
170
171     vMoments = vDXYZcg*vForces; // M = r X F
172
173     for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
174       for (ctr = 0; ctr < Coeff[axis_ctr+3].size(); ctr++) {
175         vMoments(axis_ctr+1) += Coeff[axis_ctr+3][ctr]->TotalValue();
176       }
177     }
178
179     return false;
180   } else {
181     return true;
182   }
183 }
184
185 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186
187 bool FGAerodynamics::Load(FGConfigFile* AC_cfg)
188 {
189   string parameter, axis, scratch;
190
191   AC_cfg->GetNextConfigLine();
192
193   while ((parameter = AC_cfg->GetValue()) != string("/AERODYNAMICS")) {
194     if (parameter == "AXIS") {
195       CoeffArray ca;
196       axis = AC_cfg->GetValue("NAME");
197       AC_cfg->GetNextConfigLine();
198       while ((parameter = AC_cfg->GetValue()) != string("/AXIS")) {
199         if ( parameter == "COEFFICIENT" ) {
200           ca.push_back( new FGCoefficient(FDMExec) );
201           ca.back()->Load(AC_cfg);
202         } else if ( parameter == "GROUP" ) {
203           ca.push_back( new FGFactorGroup(FDMExec) );
204           ca.back()->Load(AC_cfg);
205         }
206       }
207       Coeff[AxisIdx[axis]] = ca;
208       AC_cfg->GetNextConfigLine();
209     } else if (parameter == "AC_ALPHALIMITS") {
210       *AC_cfg >> scratch >> alphaclmin >> alphaclmax;
211       if (debug_lvl > 0) cout << "    Maximum Alpha: " << alphaclmax
212                               << "    Minimum Alpha: " << alphaclmin
213                               << endl;
214     } else if (parameter == "AC_HYSTLIMITS") {
215       *AC_cfg >> scratch >> alphahystmin >> alphahystmax;
216       if (debug_lvl > 0) cout << "    Hysteresis Start: " << alphahystmax
217                               << "    Hysteresis End: " << alphahystmin
218                               << endl;
219     }
220   }
221
222   bindModel();
223
224   return true;
225 }
226
227 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228
229 string FGAerodynamics::GetCoefficientStrings(string delimeter)
230 {
231   string CoeffStrings = "";
232   bool firstime = true;
233   unsigned int axis, sd;
234
235   for (axis = 0; axis < 6; axis++) {
236     for (sd = 0; sd < Coeff[axis].size(); sd++) {
237       if (firstime) {
238         firstime = false;
239       } else {
240         CoeffStrings += delimeter;
241       }
242       CoeffStrings += Coeff[axis][sd]->GetCoefficientName();
243     }
244   }
245   return CoeffStrings;
246 }
247
248 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249
250 string FGAerodynamics::GetCoefficientValues(string delimeter)
251 {
252   string SDValues = "";
253   bool firstime = true;
254
255   for (unsigned int axis = 0; axis < 6; axis++) {
256     for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
257       if (firstime) {
258         firstime = false;
259       } else {
260         SDValues += delimeter;
261       }
262       SDValues += Coeff[axis][sd]->GetSDstring();
263     }
264   }
265
266   return SDValues;
267 }
268
269 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270
271 void FGAerodynamics::bind(void)
272 {
273   typedef double (FGAerodynamics::*PMF)(int) const;
274
275   PropertyManager->Tie("forces/fbx-aero-lbs", this,1,
276                        (PMF)&FGAerodynamics::GetForces);
277   PropertyManager->Tie("forces/fby-aero-lbs", this,2,
278                        (PMF)&FGAerodynamics::GetForces);
279   PropertyManager->Tie("forces/fbz-aero-lbs", this,3,
280                        (PMF)&FGAerodynamics::GetForces);
281   PropertyManager->Tie("moments/l-aero-lbsft", this,1,
282                        (PMF)&FGAerodynamics::GetMoments);
283   PropertyManager->Tie("moments/m-aero-lbsft", this,2,
284                        (PMF)&FGAerodynamics::GetMoments);
285   PropertyManager->Tie("moments/n-aero-lbsft", this,3,
286                        (PMF)&FGAerodynamics::GetMoments);
287   PropertyManager->Tie("forces/fwx-aero-lbs", this,1,
288                        (PMF)&FGAerodynamics::GetvFs);
289   PropertyManager->Tie("forces/fwy-aero-lbs", this,2,
290                        (PMF)&FGAerodynamics::GetvFs);
291   PropertyManager->Tie("forces/fwz-aero-lbs", this,3,
292                        (PMF)&FGAerodynamics::GetvFs);
293   PropertyManager->Tie("forces/lod-norm", this,
294                        &FGAerodynamics::GetLoD);
295   PropertyManager->Tie("aero/cl-squared-norm", this,
296                        &FGAerodynamics::GetClSquared);
297   PropertyManager->Tie("aero/alpha-max-deg", this,
298                        &FGAerodynamics::GetAlphaCLMax,
299                        &FGAerodynamics::SetAlphaCLMax,
300                        true);
301   PropertyManager->Tie("aero/alpha-min-deg", this,
302                        &FGAerodynamics::GetAlphaCLMin,
303                        &FGAerodynamics::SetAlphaCLMin,
304                        true);
305   PropertyManager->Tie("aero/bi2vel", this,
306                        &FGAerodynamics::GetBI2Vel);
307   PropertyManager->Tie("aero/ci2vel", this,
308                        &FGAerodynamics::GetCI2Vel);
309   PropertyManager->Tie("aero/alpha-wing-rad", this,
310                        &FGAerodynamics::GetAlphaW);
311   PropertyManager->Tie("systems/stall-warn-norm", this,
312                         &FGAerodynamics::GetStallWarn);
313   PropertyManager->Tie("aero/stall-hyst-norm", this,
314                         &FGAerodynamics::GetHysteresisParm);
315 }
316
317 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318
319 void FGAerodynamics::bindModel(void)
320 {
321   unsigned i,j;
322   FGPropertyManager* node;
323   string axis_node_name;
324   node = PropertyManager->GetNode("aero/buildup",true);
325   for (i=0;i<NAxes;i++) {
326      node = node->GetNode( string(AxisNames[i]),true );
327      for (j=0; j < Coeff[i].size(); j++) {
328        Coeff[i][j]->bind(node);
329      }
330      node = (FGPropertyManager*)node->getParent();
331   }
332 }
333
334 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335
336 void FGAerodynamics::unbind(void)
337 {
338   unsigned i,j;
339
340   PropertyManager->Untie("forces/fbx-aero-lbs");
341   PropertyManager->Untie("forces/fby-aero-lbs");
342   PropertyManager->Untie("forces/fbz-aero-lbs");
343   PropertyManager->Untie("moments/l-aero-lbsft");
344   PropertyManager->Untie("moments/m-aero-lbsft");
345   PropertyManager->Untie("moments/n-aero-lbsft");
346   PropertyManager->Untie("forces/fwx-aero-lbs");
347   PropertyManager->Untie("forces/fwy-aero-lbs");
348   PropertyManager->Untie("forces/fwz-aero-lbs");
349   PropertyManager->Untie("forces/lod-norm");
350   PropertyManager->Untie("aero/cl-squared-norm");
351   PropertyManager->Untie("aero/alpha-max-deg");
352   PropertyManager->Untie("aero/alpha-min-deg");
353   PropertyManager->Untie("aero/bi2vel");
354   PropertyManager->Untie("aero/ci2vel");
355   PropertyManager->Untie("aero/alpha-wing-rad");
356   PropertyManager->Untie("aero/stall-hyst-norm");
357   PropertyManager->Untie("systems/stall-warn-norm");
358
359   for ( i=0; i<NAxes; i++ ) {
360      for ( j=0; j < Coeff[i].size(); j++ ) {
361        Coeff[i][j]->unbind();
362
363      }
364   }
365 }
366
367 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
368
369 void FGAerodynamics::convert(void)
370 {
371
372   for (int axis=0; axis<6; axis++) {
373     if (Coeff[axis].size()>0) {
374       cout << endl << "        <axis name=\"" << AxisNamesUpper[axis] << "\">" << endl;
375       for (int c=0; c<Coeff[axis].size(); c++) {
376         Coeff[axis][c]->convert();
377       }
378       cout << "        </axis>" << endl;
379     }
380   }
381
382 }
383
384 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 //    The bitmasked value choices are as follows:
386 //    unset: In this case (the default) JSBSim would only print
387 //       out the normally expected messages, essentially echoing
388 //       the config files as they are read. If the environment
389 //       variable is not set, debug_lvl is set to 1 internally
390 //    0: This requests JSBSim not to output any messages
391 //       whatsoever.
392 //    1: This value explicity requests the normal JSBSim
393 //       startup messages
394 //    2: This value asks for a message to be printed out when
395 //       a class is instantiated
396 //    4: When this value is set, a message is displayed when a
397 //       FGModel object executes its Run() method
398 //    8: When this value is set, various runtime state variables
399 //       are printed out periodically
400 //    16: When set various parameters are sanity checked and
401 //       a message is printed out when they go out of bounds
402
403 void FGAerodynamics::Debug(int from)
404 {
405   if (debug_lvl <= 0) return;
406
407   if (debug_lvl & 1) { // Standard console startup message output
408     if (from == 0) { // Constructor
409
410     }
411   }
412   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
413     if (from == 0) cout << "Instantiated: FGAerodynamics" << endl;
414     if (from == 1) cout << "Destroyed:    FGAerodynamics" << endl;
415   }
416   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
417   }
418   if (debug_lvl & 8 ) { // Runtime state variables
419   }
420   if (debug_lvl & 16) { // Sanity checking
421   }
422   if (debug_lvl & 64) {
423     if (from == 0) { // Constructor
424       cout << IdSrc << endl;
425       cout << IdHdr << endl;
426     }
427   }
428 }
429
430 } // namespace JSBSim