]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGCoefficient.cpp
#include <config.h> where needed for cygwin/gcc-3.2.
[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 static const char *IdSrc = "$Id$";
65 static const char *IdHdr = ID_COEFFICIENT;
66
67 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 CLASS IMPLEMENTATION
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
70
71 FGCoefficient::FGCoefficient( FGFDMExec* fdex )
72 {
73   FDMExec = fdex;
74   State   = FDMExec->GetState();
75   Table   = 0;
76   
77   PropertyManager = FDMExec->GetPropertyManager();
78   
79   Table = (FGTable*)0L;
80   LookupR = LookupC = 0;
81   numInstances = 0;
82   rows = columns = 0;
83
84   StaticValue  = 0.0;
85   totalValue   = 0.0;
86   bias = 0.0;
87   gain = 1.0;
88   SD = 0.0;
89
90   filename.erase();
91   description.erase();
92   name.erase();
93   method.erase();
94   multparms.erase();
95   multparmsRow.erase();
96   multparmsCol.erase();
97
98   Debug(0);
99 }
100
101 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102
103 FGCoefficient::~FGCoefficient()
104 {
105   if (Table) delete Table;
106   Debug(1);
107 }
108
109 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110
111 bool FGCoefficient::Load(FGConfigFile *AC_cfg)
112 {
113   int start, end, n;
114   string mult;
115
116   if (AC_cfg) {
117     name = AC_cfg->GetValue("NAME");
118     method = AC_cfg->GetValue("TYPE");
119     AC_cfg->GetNextConfigLine();
120     *AC_cfg >> description;
121     if      (method == "EQUATION") type = EQUATION;
122     else if (method == "TABLE")    type = TABLE;
123     else if (method == "VECTOR")   type = VECTOR;
124     else if (method == "VALUE")    type = VALUE;
125     else                           type = UNKNOWN;
126
127     if (type == VECTOR || type == TABLE) {
128       *AC_cfg >> rows;
129       if (type == TABLE) {
130         *AC_cfg >> columns;
131         Table = new FGTable(rows, columns);
132       } else {
133         Table = new FGTable(rows);
134       }
135
136       *AC_cfg >> multparmsRow;
137       LookupR = PropertyManager->GetNode( multparmsRow );
138     }
139
140     if (type == TABLE) {
141       *AC_cfg >> multparmsCol;
142
143       LookupC = PropertyManager->GetNode( multparmsCol );
144     }
145
146     // Here, read in the line of the form (e.g.) FG_MACH|FG_QBAR|FG_ALPHA
147     // where each non-dimensionalizing parameter for this coefficient is
148     // separated by a | character
149
150     string line=AC_cfg->GetCurrentLine();
151     unsigned j=0;
152     char tmp[255];
153     for(unsigned i=0;i<line.length(); i++ ) {
154       if( !isspace(line[i]) ) {
155         tmp[j]=line[i];
156         j++;
157       }
158     } 
159     tmp[j]='\0'; multparms=tmp;  
160     end  = multparms.length();
161
162     n     = multparms.find("|");
163     start = 0;
164     if (multparms != string("none")) {
165       while (n < end && n >= 0) {
166         n -= start;
167         mult = multparms.substr(start,n);
168         multipliers.push_back( resolveSymbol( mult ) );
169         start += n+1;
170         n = multparms.find("|",start);
171       }
172       mult = multparms.substr(start,n);
173       multipliers.push_back( resolveSymbol( mult ) );
174       // End of non-dimensionalizing parameter read-in
175     }
176     AC_cfg->GetNextConfigLine();
177     if (type == VALUE) {
178       *AC_cfg >> StaticValue;
179     } else if (type == VECTOR || type == TABLE) {
180       *Table << *AC_cfg;
181     } else {
182       cerr << "Unimplemented coefficient type: " << type << endl;
183     }
184
185     AC_cfg->GetNextConfigLine();
186     FGCoefficient::Debug(2);
187
188     return true;
189   } else {
190     return false;
191   }  
192 }
193
194
195
196 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197
198 double FGCoefficient::Value(double rVal, double cVal)
199 {
200   double Value;
201   unsigned int midx;
202
203   SD = Value = gain*Table->GetValue(rVal, cVal) + bias;
204
205   for (midx=0; midx < multipliers.size(); midx++) {
206       Value *= multipliers[midx]->getDoubleValue();
207   }
208   return Value;
209 }
210
211 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212
213 double FGCoefficient::Value(double Val)
214 {
215   double Value;
216   
217   SD = Value = gain*Table->GetValue(Val) + bias;
218   
219   for (unsigned int midx=0; midx < multipliers.size(); midx++) 
220       Value *= multipliers[midx]->getDoubleValue();
221   
222   return Value;
223 }
224
225 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226
227 double FGCoefficient::Value(void)
228 {
229         double Value;
230
231   SD = Value = gain*StaticValue + bias;
232
233   for (unsigned int midx=0; midx < multipliers.size(); midx++)
234     Value *= multipliers[midx]->getDoubleValue();
235
236   return Value;
237 }
238
239 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240
241 double FGCoefficient::TotalValue(void)
242 {
243   switch(type) {
244
245   case UNKNOWN:
246     totalValue = -1;
247     break;
248
249   case VALUE:
250     totalValue = Value();
251     break;
252
253   case VECTOR:
254     totalValue = Value( LookupR->getDoubleValue() );
255     break;
256
257   case TABLE:
258     totalValue = Value( LookupR->getDoubleValue(),
259                       LookupC->getDoubleValue() );
260     break;
261
262   case EQUATION:
263     totalValue = 0.0;
264     break;
265   }
266   return totalValue;
267 }
268
269 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270
271 void FGCoefficient::DisplayCoeffFactors(void)
272 {
273   unsigned int i;
274
275   cout << "   Non-Dimensionalized by: ";
276
277   if (multipliers.size() == 0) {
278     cout << "none" << endl;
279   } else {
280     for (i=0; i<multipliers.size(); i++) 
281       cout << multipliers[i]->getName() << "  ";
282   }
283   cout << endl;
284 }
285
286 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287
288 string FGCoefficient::GetSDstring(void)
289 {
290   char buffer[10];
291   string value;
292
293   sprintf(buffer,"%9.6f",SD);
294   value = string(buffer);
295   return value;
296 }
297
298 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299
300 void FGCoefficient::bind(FGPropertyManager *parent)
301 {
302   string mult;
303   unsigned i;
304   
305   node=parent->GetNode(name,true);
306   
307   node->SetString("description",description);
308   if (LookupR) node->SetString("row-parm",LookupR->getName() );
309   if (LookupC) node->SetString("column-parm",LookupC->getName() );
310   
311   mult="";
312   if (multipliers.size() == 0) 
313     mult="none";
314     
315   for (i=0; i<multipliers.size(); i++) {
316       mult += multipliers[i]->getName();
317       if ( i < multipliers.size()-1 ) mult += " "; 
318   }
319   node->SetString("multipliers",mult);
320   
321   node->Tie("SD-norm",this,&FGCoefficient::GetSD );
322   node->Tie("value-lbs",this,&FGCoefficient::GetValue );
323   
324   node->Tie("bias", this, &FGCoefficient::getBias,
325                           &FGCoefficient::setBias );
326                           
327   node->Tie("gain", this, &FGCoefficient::getGain,
328                           &FGCoefficient::setGain );
329
330 }
331
332 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333
334 void FGCoefficient::unbind(void)
335 {
336   node->Untie("SD-norm");
337   node->Untie("value-lbs"); 
338   node->Untie("bias");  
339   node->Untie("gain");
340 }
341
342 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343
344 FGPropertyManager* FGCoefficient::resolveSymbol(string name){
345         FGPropertyManager* tmpn;
346         tmpn = PropertyManager->GetNode(name,false);
347         if( !tmpn ) {
348           cerr << "Coefficient multipliers cannot create properties, check spelling?" << endl;
349           exit(1);
350         } 
351         return tmpn; 
352 }
353
354 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355 //    The bitmasked value choices are as follows:
356 //    unset: In this case (the default) JSBSim would only print
357 //       out the normally expected messages, essentially echoing
358 //       the config files as they are read. If the environment
359 //       variable is not set, debug_lvl is set to 1 internally
360 //    0: This requests JSBSim not to output any messages
361 //       whatsoever.
362 //    1: This value explicity requests the normal JSBSim
363 //       startup messages
364 //    2: This value asks for a message to be printed out when
365 //       a class is instantiated
366 //    4: When this value is set, a message is displayed when a
367 //       FGModel object executes its Run() method
368 //    8: When this value is set, various runtime state variables
369 //       are printed out periodically
370 //    16: When set various parameters are sanity checked and
371 //       a message is printed out when they go out of bounds
372
373 void FGCoefficient::Debug(int from)
374 {
375   if (debug_lvl <= 0) return;
376
377   if (debug_lvl & 1) { // Standard console startup message output
378     
379     if (from == 2) { // Loading
380       cout << "\n   " << highint << underon << name << underoff << normint << endl;
381       cout << "   " << description << endl;
382       cout << "   " << method << endl;
383
384       if (type == VECTOR || type == TABLE) {
385         cout << "   Rows: " << rows << " ";
386         if (type == TABLE) {
387           cout << "Cols: " << columns;
388         }
389         cout << endl << "   Row indexing parameter: " << LookupR->getName() << endl;
390       }
391
392       if (type == TABLE) {
393         cout << "   Column indexing parameter: " << LookupC->getName() << endl;
394       }
395
396       if (type == VALUE) {
397         cout << "      Value = " << StaticValue << endl;
398       } else if (type == VECTOR || type == TABLE) {
399         Table->Print();
400       }
401
402       DisplayCoeffFactors();
403     }
404   }
405   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
406     if (from == 0) cout << "Instantiated: FGCoefficient" << endl;
407     if (from == 1) cout << "Destroyed:    FGCoefficient" << endl;
408   }
409   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
410   }
411   if (debug_lvl & 8 ) { // Runtime state variables
412   }
413   if (debug_lvl & 16) { // Sanity checking
414   }
415   if (debug_lvl & 64) {
416     if (from == 0) { // Constructor
417       cout << IdSrc << endl;
418       cout << IdHdr << endl;
419     }
420   }
421 }
422