]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGCoefficient.cpp
Adds a basic FDM model for LaRCsim debugging purposes.
[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 {
348   FGPropertyManager* tmpn;
349
350   tmpn = PropertyManager->GetNode(name,false);
351   if ( !tmpn ) {
352     cerr << "Coefficient multipliers cannot create properties, check spelling?" << endl;
353     exit(1);
354   } 
355   return tmpn; 
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 FGCoefficient::Debug(int from)
378 {
379   if (debug_lvl <= 0) return;
380
381   if (debug_lvl & 1) { // Standard console startup message output
382     
383     if (from == 2) { // Loading
384       cout << "\n   " << highint << underon << name << underoff << normint << endl;
385       cout << "   " << description << endl;
386       cout << "   " << method << endl;
387
388       if (type == VECTOR || type == TABLE) {
389         cout << "   Rows: " << rows << " ";
390         if (type == TABLE) {
391           cout << "Cols: " << columns;
392         }
393         cout << endl << "   Row indexing parameter: " << LookupR->getName() << endl;
394       }
395
396       if (type == TABLE) {
397         cout << "   Column indexing parameter: " << LookupC->getName() << endl;
398       }
399
400       if (type == VALUE) {
401         cout << "      Value = " << StaticValue << endl;
402       } else if (type == VECTOR || type == TABLE) {
403         Table->Print();
404       }
405
406       DisplayCoeffFactors();
407     }
408   }
409   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
410     if (from == 0) cout << "Instantiated: FGCoefficient" << endl;
411     if (from == 1) cout << "Destroyed:    FGCoefficient" << endl;
412   }
413   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
414   }
415   if (debug_lvl & 8 ) { // Runtime state variables
416   }
417   if (debug_lvl & 16) { // Sanity checking
418   }
419   if (debug_lvl & 64) {
420     if (from == 0) { // Constructor
421       cout << IdSrc << endl;
422       cout << IdHdr << endl;
423     }
424   }
425 }
426
427 } // namespace JSBSim