]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGCoefficient.cpp
Connect the FlightGear /environment/turbulence-norm property to the
[flightgear.git] / src / FDM / JSBSim / FGCoefficient.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGCoefficient.cpp
4  Author:       Jon S. Berndt
5  Date started: 12/28/98
6  Purpose:      Encapsulates the stability derivative class FGCoefficient;
7  Called by:    FGAircraft
8
9  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
10
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  details.
20
21  You should have received a copy of the GNU General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA  02111-1307, USA.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This class models the stability derivative coefficient lookup tables or
31 equations. Note that the coefficients need not be calculated each delta-t.
32
33 Note that the values in a row which index into the table must be the same value
34 for each column of data, so the first column of numbers for each altitude are
35 seen to be equal, and there are the same number of values for each altitude.
36
37 See the header file FGCoefficient.h for the values of the identifiers.
38
39 HISTORY
40 --------------------------------------------------------------------------------
41 12/28/98   JSB   Created
42
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 INCLUDES
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
46
47 #include <stdio.h>
48
49 #include "FGCoefficient.h"
50 #include "FGState.h"
51 #include "FGFDMExec.h"
52 #include "FGPropertyManager.h"
53
54 #ifndef FGFS
55 #  if defined(sgi) && !defined(__GNUC__)
56 #    include <iomanip.h>
57 #  else
58 #    include <iomanip>
59 #  endif
60 #else
61 #  include STL_IOMANIP
62 #endif
63
64 namespace JSBSim {
65
66 static const char *IdSrc = "$Id$";
67 static const char *IdHdr = ID_COEFFICIENT;
68
69 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 CLASS IMPLEMENTATION
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
72
73 FGCoefficient::FGCoefficient( FGFDMExec* fdex )
74 {
75   FDMExec = fdex;
76   State   = FDMExec->GetState();
77   Table   = 0;
78   
79   PropertyManager = FDMExec->GetPropertyManager();
80   
81   Table = (FGTable*)0L;
82   LookupR = LookupC = 0;
83   numInstances = 0;
84   rows = columns = 0;
85
86   StaticValue  = 0.0;
87   totalValue   = 0.0;
88   bias = 0.0;
89   gain = 1.0;
90   SD = 0.0;
91
92   filename.erase();
93   description.erase();
94   name.erase();
95   method.erase();
96   multparms.erase();
97   multparmsRow.erase();
98   multparmsCol.erase();
99
100   Debug(0);
101 }
102
103 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104
105 FGCoefficient::~FGCoefficient()
106 {
107   if (Table) delete Table;
108   Debug(1);
109 }
110
111 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112
113 bool FGCoefficient::Load(FGConfigFile *AC_cfg)
114 {
115   int start, end, n;
116   string mult;
117
118   if (AC_cfg) {
119     name = AC_cfg->GetValue("NAME");
120     method = AC_cfg->GetValue("TYPE");
121     AC_cfg->GetNextConfigLine();
122     *AC_cfg >> description;
123     if      (method == "EQUATION") type = EQUATION;
124     else if (method == "TABLE")    type = TABLE;
125     else if (method == "VECTOR")   type = VECTOR;
126     else if (method == "VALUE")    type = VALUE;
127     else                           type = UNKNOWN;
128
129     if (type == VECTOR || type == TABLE) {
130       *AC_cfg >> rows;
131       if (type == TABLE) {
132         *AC_cfg >> columns;
133         Table = new FGTable(rows, columns);
134       } else {
135         Table = new FGTable(rows);
136       }
137
138       *AC_cfg >> multparmsRow;
139       LookupR = PropertyManager->GetNode( multparmsRow );
140     }
141
142     if (type == TABLE) {
143       *AC_cfg >> multparmsCol;
144
145       LookupC = PropertyManager->GetNode( multparmsCol );
146     }
147
148     // Here, read in the line of the form (e.g.) FG_MACH|FG_QBAR|FG_ALPHA
149     // where each non-dimensionalizing parameter for this coefficient is
150     // separated by a | character
151
152     string line=AC_cfg->GetCurrentLine();
153     unsigned j=0;
154     char tmp[255];
155     for(unsigned i=0;i<line.length(); i++ ) {
156       if( !isspace(line[i]) ) {
157         tmp[j]=line[i];
158         j++;
159       }
160     } 
161     tmp[j]='\0'; multparms=tmp;  
162     end  = multparms.length();
163
164     n     = multparms.find("|");
165     start = 0;
166     if (multparms != string("none")) {
167       while (n < end && n >= 0) {
168         n -= start;
169         mult = multparms.substr(start,n);
170         multipliers.push_back( resolveSymbol( mult ) );
171         start += n+1;
172         n = multparms.find("|",start);
173       }
174       mult = multparms.substr(start,n);
175       multipliers.push_back( resolveSymbol( mult ) );
176       // End of non-dimensionalizing parameter read-in
177     }
178     AC_cfg->GetNextConfigLine();
179     if (type == VALUE) {
180       *AC_cfg >> StaticValue;
181     } else if (type == VECTOR || type == TABLE) {
182       *Table << *AC_cfg;
183     } else {
184       cerr << "Unimplemented coefficient type: " << type << endl;
185     }
186
187     AC_cfg->GetNextConfigLine();
188     FGCoefficient::Debug(2);
189
190     return true;
191   } else {
192     return false;
193   }  
194 }
195
196
197
198 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199
200 double FGCoefficient::Value(double rVal, double cVal)
201 {
202   double Value;
203   unsigned int midx;
204
205   SD = Value = gain*Table->GetValue(rVal, cVal) + bias;
206
207   for (midx=0; midx < multipliers.size(); midx++) {
208       Value *= multipliers[midx]->getDoubleValue();
209   }
210   return Value;
211 }
212
213 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214
215 double FGCoefficient::Value(double Val)
216 {
217   double Value;
218   
219   SD = Value = gain*Table->GetValue(Val) + bias;
220   
221   for (unsigned int midx=0; midx < multipliers.size(); midx++) 
222       Value *= multipliers[midx]->getDoubleValue();
223   
224   return Value;
225 }
226
227 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228
229 double FGCoefficient::Value(void)
230 {
231         double Value;
232
233   SD = Value = gain*StaticValue + bias;
234
235   for (unsigned int midx=0; midx < multipliers.size(); midx++)
236     Value *= multipliers[midx]->getDoubleValue();
237
238   return Value;
239 }
240
241 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242
243 double FGCoefficient::TotalValue(void)
244 {
245   switch(type) {
246
247   case UNKNOWN:
248     totalValue = -1;
249     break;
250
251   case VALUE:
252     totalValue = Value();
253     break;
254
255   case VECTOR:
256     totalValue = Value( LookupR->getDoubleValue() );
257     break;
258
259   case TABLE:
260     totalValue = Value( LookupR->getDoubleValue(),
261                       LookupC->getDoubleValue() );
262     break;
263
264   case EQUATION:
265     totalValue = 0.0;
266     break;
267   }
268   return totalValue;
269 }
270
271 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272
273 void FGCoefficient::DisplayCoeffFactors(void)
274 {
275   unsigned int i;
276
277   cout << "   Non-Dimensionalized by: ";
278
279   if (multipliers.size() == 0) {
280     cout << "none" << endl;
281   } else {
282     for (i=0; i<multipliers.size(); i++) 
283       cout << multipliers[i]->getName() << "  ";
284   }
285   cout << endl;
286 }
287
288 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289
290 string FGCoefficient::GetSDstring(void)
291 {
292   char buffer[10];
293   string value;
294
295   sprintf(buffer,"%9.6f",SD);
296   value = string(buffer);
297   return value;
298 }
299
300 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301
302 void FGCoefficient::bind(FGPropertyManager *parent)
303 {
304   string mult;
305   unsigned i;
306   
307   node=parent->GetNode(name,true);
308   
309   node->SetString("description",description);
310   if (LookupR) node->SetString("row-parm",LookupR->getName() );
311   if (LookupC) node->SetString("column-parm",LookupC->getName() );
312   
313   mult="";
314   if (multipliers.size() == 0) 
315     mult="none";
316     
317   for (i=0; i<multipliers.size(); i++) {
318       mult += multipliers[i]->getName();
319       if ( i < multipliers.size()-1 ) mult += " "; 
320   }
321   node->SetString("multipliers",mult);
322   
323   node->Tie("SD-norm",this,&FGCoefficient::GetSD );
324   node->Tie("value-lbs",this,&FGCoefficient::GetValue );
325   
326   node->Tie("bias", this, &FGCoefficient::getBias,
327                           &FGCoefficient::setBias );
328                           
329   node->Tie("gain", this, &FGCoefficient::getGain,
330                           &FGCoefficient::setGain );
331
332 }
333
334 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335
336 void FGCoefficient::unbind(void)
337 {
338   node->Untie("SD-norm");
339   node->Untie("value-lbs"); 
340   node->Untie("bias");  
341   node->Untie("gain");
342 }
343
344 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345
346 FGPropertyManager* FGCoefficient::resolveSymbol(string name){
347         FGPropertyManager* tmpn;
348         tmpn = PropertyManager->GetNode(name,false);
349         if( !tmpn ) {
350           cerr << "Coefficient multipliers cannot create properties, check spelling?" << endl;
351           exit(1);
352         } 
353         return tmpn; 
354 }
355
356 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357 //    The bitmasked value choices are as follows:
358 //    unset: In this case (the default) JSBSim would only print
359 //       out the normally expected messages, essentially echoing
360 //       the config files as they are read. If the environment
361 //       variable is not set, debug_lvl is set to 1 internally
362 //    0: This requests JSBSim not to output any messages
363 //       whatsoever.
364 //    1: This value explicity requests the normal JSBSim
365 //       startup messages
366 //    2: This value asks for a message to be printed out when
367 //       a class is instantiated
368 //    4: When this value is set, a message is displayed when a
369 //       FGModel object executes its Run() method
370 //    8: When this value is set, various runtime state variables
371 //       are printed out periodically
372 //    16: When set various parameters are sanity checked and
373 //       a message is printed out when they go out of bounds
374
375 void FGCoefficient::Debug(int from)
376 {
377   if (debug_lvl <= 0) return;
378
379   if (debug_lvl & 1) { // Standard console startup message output
380     
381     if (from == 2) { // Loading
382       cout << "\n   " << highint << underon << name << underoff << normint << endl;
383       cout << "   " << description << endl;
384       cout << "   " << method << endl;
385
386       if (type == VECTOR || type == TABLE) {
387         cout << "   Rows: " << rows << " ";
388         if (type == TABLE) {
389           cout << "Cols: " << columns;
390         }
391         cout << endl << "   Row indexing parameter: " << LookupR->getName() << endl;
392       }
393
394       if (type == TABLE) {
395         cout << "   Column indexing parameter: " << LookupC->getName() << endl;
396       }
397
398       if (type == VALUE) {
399         cout << "      Value = " << StaticValue << endl;
400       } else if (type == VECTOR || type == TABLE) {
401         Table->Print();
402       }
403
404       DisplayCoeffFactors();
405     }
406   }
407   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
408     if (from == 0) cout << "Instantiated: FGCoefficient" << endl;
409     if (from == 1) cout << "Destroyed:    FGCoefficient" << endl;
410   }
411   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
412   }
413   if (debug_lvl & 8 ) { // Runtime state variables
414   }
415   if (debug_lvl & 16) { // Sanity checking
416   }
417   if (debug_lvl & 64) {
418     if (from == 0) { // Constructor
419       cout << IdSrc << endl;
420       cout << IdHdr << endl;
421     }
422   }
423 }
424
425 } // namespace JSBSim