]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGCoefficient.cpp
Typo
[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 #ifdef HAVE_CONFIG_H
48 #  include <config.h>
49 #endif
50
51 #include <stdio.h>
52
53 #include "FGCoefficient.h"
54 #include "FGState.h"
55 #include "FGFDMExec.h"
56 #include "FGPropertyManager.h"
57
58 #ifndef FGFS
59 #  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
60 #    include <iomanip.h>
61 #  else
62 #    include <iomanip>
63 #  endif
64 #else
65 #  include STL_IOMANIP
66 #endif
67
68 namespace JSBSim {
69
70 static const char *IdSrc = "$Id$";
71 static const char *IdHdr = ID_COEFFICIENT;
72
73 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 CLASS IMPLEMENTATION
75 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
76
77 FGCoefficient::FGCoefficient( FGFDMExec* fdex )
78 {
79   FDMExec = fdex;
80   State   = FDMExec->GetState();
81   Table   = 0;
82   IsFactor = false;
83
84   PropertyManager = FDMExec->GetPropertyManager();
85
86   Table = (FGTable*)0L;
87   LookupR = LookupC = 0;
88   numInstances = 0;
89   rows = columns = tables = 0;
90
91   StaticValue  = 0.0;
92   totalValue   = 0.0;
93   bias = 0.0;
94   gain = 1.0;
95   SD = 0.0;
96
97   filename.erase();
98   description.erase();
99   name.erase();
100   method.erase();
101   multparms.erase();
102   multparmsRow.erase();
103   multparmsCol.erase();
104
105   Debug(0);
106 }
107
108 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109
110 FGCoefficient::~FGCoefficient()
111 {
112   if (Table) delete Table;
113   Debug(1);
114 }
115
116 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
118 bool FGCoefficient::Load(FGConfigFile *AC_cfg)
119 {
120   int start, end, n;
121   string mult;
122
123   if (AC_cfg) {
124     name = AC_cfg->GetValue("NAME");
125     method = AC_cfg->GetValue("TYPE");
126     AC_cfg->GetNextConfigLine();
127     *AC_cfg >> description;
128     if      (method == "EQUATION") type = EQUATION;
129     else if (method == "TABLE")    type = TABLE;
130     else if (method == "TABLE3D")  type = TABLE3D;
131     else if (method == "VECTOR")   type = VECTOR;
132     else if (method == "VALUE")    type = VALUE;
133     else                           type = UNKNOWN;
134
135     if (type == VECTOR || type == TABLE || type == TABLE3D) {
136
137       if (type == TABLE3D) {
138         *AC_cfg >> rows >> columns >> tables;
139         Table = new FGTable(rows, columns, tables);
140         *AC_cfg >> multparmsRow >> multparmsCol >> multparmsTable;
141         LookupR = PropertyManager->GetNode( multparmsRow );
142         LookupC = PropertyManager->GetNode( multparmsCol );
143         LookupT = PropertyManager->GetNode( multparmsTable );
144       } else if (type == TABLE) {
145         *AC_cfg >> rows >> columns;
146         Table = new FGTable(rows, columns);
147         *AC_cfg >> multparmsRow >> multparmsCol;
148         LookupR = PropertyManager->GetNode( multparmsRow );
149         LookupC = PropertyManager->GetNode( multparmsCol );
150       } else {
151         *AC_cfg >> rows;
152         Table = new FGTable(rows);
153         *AC_cfg >> multparmsRow;
154         LookupR = PropertyManager->GetNode( multparmsRow );
155       }
156     }
157
158     // Here, read in the line of the form:
159     // {property1} | {property2} | {property3}
160     // where each non-dimensionalizing property for this coefficient is
161     // separated by a | character
162
163     string line=AC_cfg->GetCurrentLine();
164     unsigned j=0;
165     char tmp[255];
166     for(unsigned i=0;i<line.length(); i++ ) {
167       if( !isspace(line[i]) ) {
168         tmp[j]=line[i];
169         j++;
170       }
171     }
172     tmp[j]='\0'; multparms=tmp;
173     end = multparms.length();
174
175     n = multparms.find("|");
176     if (n == string::npos) n = end;
177     start = 0;
178     if (multparms != string("none")) {
179       while (n < end && n != string::npos) {
180         n -= start;
181         mult = multparms.substr(start,n);
182         multipliers.push_back( resolveSymbol( mult ) );
183         start += n+1;
184         n = multparms.find("|",start);
185       }
186       mult = multparms.substr(start,n);
187       multipliers.push_back( resolveSymbol( mult ) );
188       // End of non-dimensionalizing parameter read-in
189     }
190     AC_cfg->GetNextConfigLine();
191
192     if (type == VALUE) {
193       *AC_cfg >> StaticValue;
194     } else if (type == VECTOR || type == TABLE || type == TABLE3D) {
195       *Table << *AC_cfg;
196     } else {
197       cerr << "Unimplemented coefficient type: " << type << endl;
198     }
199
200     AC_cfg->GetNextConfigLine();
201     FGCoefficient::Debug(2);
202
203     return true;
204   } else {
205     return false;
206   }
207 }
208
209
210
211 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212
213 double FGCoefficient::Value(double rVal, double cVal, double tVal)
214 {
215   double Value;
216   unsigned int midx;
217
218   SD = Value = gain*Table->GetValue(rVal, cVal, tVal) + bias;
219
220   for (midx=0; midx < multipliers.size(); midx++) {
221       Value *= multipliers[midx]->getDoubleValue();
222   }
223   return Value;
224 }
225
226 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227
228 double FGCoefficient::Value(double rVal, double cVal)
229 {
230   double Value;
231   unsigned int midx;
232
233   SD = Value = gain*Table->GetValue(rVal, cVal) + bias;
234
235   for (midx=0; midx < multipliers.size(); midx++) {
236       Value *= multipliers[midx]->getDoubleValue();
237   }
238   return Value;
239 }
240
241 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242
243 double FGCoefficient::Value(double Val)
244 {
245   double Value;
246
247   SD = Value = gain*Table->GetValue(Val) + bias;
248
249   for (unsigned int midx=0; midx < multipliers.size(); midx++)
250       Value *= multipliers[midx]->getDoubleValue();
251
252   return Value;
253 }
254
255 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256
257 double FGCoefficient::Value(void)
258 {
259   double Value;
260
261   SD = Value = gain*StaticValue + bias;
262
263   for (unsigned int midx=0; midx < multipliers.size(); midx++)
264     Value *= multipliers[midx]->getDoubleValue();
265
266   return Value;
267 }
268
269 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270
271 double FGCoefficient::TotalValue(void)
272 {
273   switch(type) {
274
275   case UNKNOWN:
276     totalValue = -1;
277     break;
278
279   case VALUE:
280     totalValue = Value();
281     break;
282
283   case VECTOR:
284     totalValue = Value( LookupR->getDoubleValue() );
285     break;
286
287   case TABLE:
288     totalValue = Value( LookupR->getDoubleValue(),
289                         LookupC->getDoubleValue() );
290     break;
291
292   case TABLE3D:
293     totalValue = Value( LookupR->getDoubleValue(),
294                         LookupC->getDoubleValue(),
295                         LookupT->getDoubleValue() );
296     break;
297
298   case EQUATION:
299     totalValue = 0.0;
300     break;
301   }
302   return totalValue;
303 }
304
305 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306
307 void FGCoefficient::DisplayCoeffFactors(void)
308 {
309   unsigned int i;
310
311   cout << "   Non-Dimensionalized by: ";
312
313   if (multipliers.size() == 0) {
314     cout << "none" << endl;
315   } else {
316     for (i=0; i<multipliers.size(); i++)
317       cout << multipliers[i]->getName() << "  ";
318   }
319   cout << endl;
320 }
321
322 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323
324 string FGCoefficient::GetSDstring(void)
325 {
326   char buffer[20];
327   string value;
328
329   sprintf(buffer,"%9.6f",SD);
330   value = string(buffer);
331   return value;
332 }
333
334 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335
336 void FGCoefficient::bind(FGPropertyManager *parent)
337 {
338   string mult;
339   unsigned i;
340
341   node = parent->GetNode(name,true);
342
343   node->SetString("description",description);
344   if (LookupR) node->SetString("row-parm",LookupR->getName() );
345   if (LookupC) node->SetString("column-parm",LookupC->getName() );
346
347   mult="";
348   if (multipliers.size() == 0)
349     mult="none";
350
351   for (i=0; i<multipliers.size(); i++) {
352       mult += multipliers[i]->getName();
353       if ( i < multipliers.size()-1 ) mult += " ";
354   }
355   node->SetString("multipliers",mult);
356
357   node->Tie("SD-norm",this,&FGCoefficient::GetSD );
358   node->Tie("value-lbs",this,&FGCoefficient::GetValue );
359
360   node->Tie("bias", this, &FGCoefficient::getBias,
361                           &FGCoefficient::setBias );
362
363   node->Tie("gain", this, &FGCoefficient::getGain,
364                           &FGCoefficient::setGain );
365
366 }
367
368 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369
370 void FGCoefficient::unbind(void)
371 {
372   node->Untie("SD-norm");
373   node->Untie("value-lbs");
374   node->Untie("bias");
375   node->Untie("gain");
376 }
377
378 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379
380 FGPropertyManager* FGCoefficient::resolveSymbol(string name)
381 {
382   FGPropertyManager* tmpn;
383
384   tmpn = PropertyManager->GetNode(name,false);
385   if ( !tmpn ) {
386     cerr << "Coefficient multipliers cannot create properties, check spelling?" << endl;
387     exit(1);
388   }
389   return tmpn;
390 }
391
392 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393
394 void FGCoefficient::convert(string prop)
395 {
396   if (IsFactor)
397     cout << "            <function name=\"aero/function/" << name << "\">" << endl;
398   else
399     cout << "            <function name=\"aero/coefficient/" << name << "\">" << endl;
400
401   cout << "                <description>" << description << "</description>" << endl;
402   cout << "                <product>" << endl;
403
404   for (int i=0; i<multipliers.size(); i++)
405     cout << "                    <property>" << (multipliers[i]->GetFullyQualifiedName()).substr(12) << "</property>" << endl;
406
407   if (!prop.empty())
408     cout << "                    <property>aero/function/" << prop << "</property>" << endl;
409
410   switch (type) {
411   case VALUE:
412   cout << "                    <value>" << StaticValue << "</value>" << endl;
413     break;
414
415   case VECTOR:
416     cout << "                      <table>" << endl;
417     cout << "                          <independentVar>" << (LookupR->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
418     cout << "                          <tableData>" << endl;
419     Table->Print(30);
420     cout << "                          </tableData>" << endl;
421     cout << "                      </table>" << endl;
422     break;
423
424   case TABLE:
425     cout << "                      <table>" << endl;
426     cout << "                          <independentVar lookup=\"row\">" << (LookupR->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
427     cout << "                          <independentVar lookup=\"column\">" << (LookupC->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
428     cout << "                          <tableData>" << endl;
429     Table->Print(30);
430     cout << "                          </tableData>" << endl;
431     cout << "                      </table>" << endl;
432     break;
433
434   case TABLE3D:
435     cout << "                      <table>" << endl;
436     cout << "                          <independentVar lookup=\"row\">" << (LookupR->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
437     cout << "                          <independentVar lookup=\"column\">" << (LookupC->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
438     cout << "                          <independentVar lookup=\"table\">" << (LookupT->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
439     cout << "                          <tableData>" << endl;
440     Table->Print(30);
441     cout << "                          </tableData>" << endl;
442     cout << "                      </table>" << endl;
443     break;
444
445   }
446
447   cout << "                </product>" << endl;
448   cout << "            </function>" << endl;
449
450   if (IsFactor) {
451   cout << " === MOVE THE ABOVE FACTOR " << name << " OUTSIDE OF AND BEFORE ANY <AXIS> DEFINITION ===" << endl;
452     for (int i=0; i<sum.size(); i++) {
453       sum[i]->convert(name);
454     }
455   }
456 }
457
458 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 //    The bitmasked value choices are as follows:
460 //    unset: In this case (the default) JSBSim would only print
461 //       out the normally expected messages, essentially echoing
462 //       the config files as they are read. If the environment
463 //       variable is not set, debug_lvl is set to 1 internally
464 //    0: This requests JSBSim not to output any messages
465 //       whatsoever.
466 //    1: This value explicity requests the normal JSBSim
467 //       startup messages
468 //    2: This value asks for a message to be printed out when
469 //       a class is instantiated
470 //    4: When this value is set, a message is displayed when a
471 //       FGModel object executes its Run() method
472 //    8: When this value is set, various runtime state variables
473 //       are printed out periodically
474 //    16: When set various parameters are sanity checked and
475 //       a message is printed out when they go out of bounds
476
477 void FGCoefficient::Debug(int from)
478 {
479   if (debug_lvl <= 0) return;
480
481   if (debug_lvl & 1) { // Standard console startup message output
482
483     if (from == 2) { // Loading
484       cout << "\n   " << highint << underon << name << underoff << normint << endl;
485       cout << "   " << description << endl;
486       cout << "   " << method << endl;
487
488       if (type == VECTOR || type == TABLE || type == TABLE3D) {
489         cout << "   Rows: " << rows << " indexed by: " << LookupR->getName() << endl;
490         if (type == TABLE || type == TABLE3D) {
491           cout << "   Cols: " << columns << " indexed by: " << LookupC->getName() << endl;
492           if (type == TABLE3D) {
493             cout << "   Tables: " << tables << " indexed by: " << LookupT->getName() << endl;
494           }
495         }
496         Table->Print();
497       } else if (type == VALUE) {
498         cout << "      Value = " << StaticValue << endl;
499       }
500
501       DisplayCoeffFactors();
502     }
503   }
504   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
505     if (from == 0) cout << "Instantiated: FGCoefficient" << endl;
506     if (from == 1) cout << "Destroyed:    FGCoefficient" << endl;
507   }
508   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
509   }
510   if (debug_lvl & 8 ) { // Runtime state variables
511   }
512   if (debug_lvl & 16) { // Sanity checking
513   }
514   if (debug_lvl & 64) {
515     if (from == 0) { // Constructor
516       cout << IdSrc << endl;
517       cout << IdHdr << endl;
518     }
519   }
520 }
521
522 } // namespace JSBSim