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