]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGCoefficient.cpp
FG_HAVE_STD_INCLUDES -> SG_HAVE_STD_INCLUDES
[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 "FGCoefficient.h"
48 #include "FGState.h"
49 #include "FGFDMExec.h"
50
51 #include <iomanip.h>
52
53 static const char *IdSrc = "$Header$";
54 static const char *IdHdr = "ID_COEFFICIENT";
55
56 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 CLASS IMPLEMENTATION
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59
60 FGCoefficient::FGCoefficient(FGFDMExec* fdex, FGConfigFile* AC_cfg)
61 {
62   int r, c, start, end, n;
63   float ftrashcan;
64   string multparms;
65   char nullstring[13] = "            ";
66   
67   bias =0.0;
68   gain = 1.0;
69   
70   FDMExec     = fdex;
71   State       = FDMExec->GetState();
72   Table = 0;
73
74   if (AC_cfg) {
75     name = AC_cfg->GetValue("NAME");
76     method = AC_cfg->GetValue("TYPE");
77
78     AC_cfg->GetNextConfigLine();
79     *AC_cfg >> description;
80
81     char bolden[5];
82     char unbolden[5];
83
84     bolden[0] = 27;
85     bolden[1] = '[';
86     bolden[2] = '1';
87     bolden[3] = 'm';
88     bolden[4] = '\0';
89
90     unbolden[0] = 27;
91     unbolden[1] = '[';
92     unbolden[2] = '0';
93     unbolden[3] = 'm';
94     unbolden[4] = '\0';
95
96     cout << "   " << bolden << name << unbolden << endl;
97     cout << "   " << description << endl;
98     cout << "   " << method << endl;
99
100     if      (method == "EQUATION") type = EQUATION;
101     else if (method == "TABLE")    type = TABLE;
102     else if (method == "VECTOR")   type = VECTOR;
103     else if (method == "VALUE")    type = VALUE;
104     else                           type = UNKNOWN;
105
106     if (type == VECTOR || type == TABLE) {
107       *AC_cfg >> rows;
108       cout << "   Rows: " << rows << " ";
109       if (type == TABLE) {
110         *AC_cfg >> columns;
111         cout << "Cols: " << columns;
112       }
113
114       cout << endl;
115
116       *AC_cfg >> multparms;
117       LookupR = State->GetParameterIndex(multparms);
118       cout << "   Row indexing parameter: " << multparms << endl;
119     }
120
121     if (type == TABLE) {
122       *AC_cfg >> multparms;
123       LookupC = State->GetParameterIndex(multparms);
124       cout << "   Column indexing parameter: " << multparms << endl;
125     }
126
127     // Here, read in the line of the form (e.g.) FG_MACH|FG_QBAR|FG_ALPHA
128     // where each non-dimensionalizing parameter for this coefficient is
129     // separated by a | character
130
131     *AC_cfg >> multparms;
132
133     end   = multparms.length();
134     n     = multparms.find("|");
135     start = 0;
136
137     while (n < end && n >= 0) {
138       n -= start;
139       multipliers.push_back(State->GetParameterIndex(multparms.substr(start,n)));
140       start += n+1;
141       n = multparms.find("|",start);
142     }
143
144     multipliers.push_back(State->GetParameterIndex(multparms.substr(start,n)));
145
146     // End of non-dimensionalizing parameter read-in
147
148     switch(type) {
149     case VALUE:
150       *AC_cfg >> StaticValue;
151       cout << "      Value = " << StaticValue << endl;
152       break;
153     case VECTOR:
154       Allocate(rows,2);
155
156       for (r=1;r<=rows;r++) {
157         *AC_cfg >> Table[r][0];
158         *AC_cfg >> Table[r][1];
159       }
160
161       for (r=1;r<=rows;r++) {
162         cout << "       ";
163         for (c=0;c<columns;c++) {
164           cout << Table[r][c] << "      ";
165         }
166         cout << endl;
167       }
168
169       break;
170     case TABLE:
171       Allocate(rows, columns);
172
173       Table[0][0] = 0.0;
174
175       // Read the table in -- it should be in matrix format with the row
176       // independents as the first column and the column independents in
177       // the first row.  The implication of this layout is that there should
178       // be no value in the upper left corner of the matrix e.g:
179       //      0  10  20 30 ...
180       // -5   1  2   3  4  ...
181       //  ...
182
183       for (r=0; r<=rows; r++) {
184         for (c=0; c <= columns; c++) {
185           if ( !((r == 0) && (c == 0)) ) {
186             *AC_cfg >> Table[r][c];
187           }
188         }
189       }   
190       
191       /* for (c=1;c<=columns;c++) {
192         *AC_cfg >> Table[0][c];
193         for (r=1;r<=rows;r++) {
194           if ( c==1 ) *AC_cfg >> Table[r][0];
195           else *AC_cfg >> ftrashcan;
196           *AC_cfg >> Table[r][c];
197         }
198       } */
199       
200       for (r=0;r<=rows;r++) {
201         cout << "       ";
202         for (c=0;c<=columns;c++) {
203           if( ((r == 0) && (c == 0)) ) {
204              cout << nullstring;
205           } else {
206              cout.flags(ios::left);
207              cout << setw(12) << Table[r][c];
208           }
209         }
210         cout << endl;
211       }
212
213       break;
214     case EQUATION:
215     case UNKNOWN:
216       cerr << "Unimplemented coefficient type: " << type << endl;
217       break;  
218     }
219     AC_cfg->GetNextConfigLine();
220   }
221 }
222
223 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224
225 FGCoefficient::~FGCoefficient(void) {
226   DeAllocate();
227 }
228
229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230
231 bool FGCoefficient::DeAllocate(void)
232 {
233   if (Table != NULL ) {
234     for (unsigned int i=0; i<=rows; i++) delete[] Table[i];
235     
236     delete[] Table;
237   } 
238   
239   return true;
240 }
241
242 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243
244 bool FGCoefficient::Allocate(int r, int c)
245 {
246   rows = r;
247   columns = c;
248   Table = new float*[r+1];
249   for (int i=0;i<=r;i++) Table[i] = new float[c+1];
250   return true;
251 }
252
253 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254
255 float FGCoefficient::Value(float rVal, float cVal)
256 {
257   float rFactor, cFactor, col1temp, col2temp, Value;
258   int r, c;
259   unsigned midx;
260
261   if (rows < 2 || columns < 2) return 0.0;
262
263   for (r=1;r<=rows;r++) if (Table[r][0] >= rVal) break;
264   for (c=1;c<=columns;c++) if (Table[0][c] >= cVal) break;
265   //cout << "Value(): rVal: " << rVal << " cVal: " << cVal << endl;
266   //cout << "Value(): r: " << r << " c: " << c << endl;
267   c = c < 2 ? 2 : (c > columns ? columns : c);
268   r = r < 2 ? 2 : (r > rows    ? rows    : r);
269
270   rFactor = (rVal - Table[r-1][0]) / (Table[r][0] - Table[r-1][0]);
271   cFactor = (cVal - Table[0][c-1]) / (Table[0][c] - Table[0][c-1]);
272
273   col1temp = rFactor*(Table[r][c-1] - Table[r-1][c-1]) + Table[r-1][c-1];
274   col2temp = rFactor*(Table[r][c] - Table[r-1][c]) + Table[r-1][c];
275
276   Value = col1temp + cFactor*(col2temp - col1temp);
277   Value = (Value + bias)*gain;
278   SD = Value;
279   
280   for (midx=0; midx < multipliers.size(); midx++) {
281     Value *= State->GetParameter(multipliers[midx]);
282   }
283
284   return Value;
285 }
286
287 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288
289 float FGCoefficient::Value(float Val)
290 {
291   
292   
293   float Factor, Value;
294   int r;
295   unsigned midx;
296
297   if (rows < 2) return 0.0;
298
299   for (r=1;r<=rows;r++) if (Table[r][0] >= Val) break;
300   r = r < 2 ? 2 : (r > rows    ? rows    : r);
301
302   // make sure denominator below does not go to zero.
303   if (Table[r][0] != Table[r-1][0]) {
304     Factor = (Val - Table[r-1][0]) / (Table[r][0] - Table[r-1][0]);
305   } else {
306     Factor = 1.0;
307   }
308
309   Value = Factor*(Table[r][1] - Table[r-1][1]) + Table[r-1][1];
310   Value = (Value + bias)*gain;
311   SD = Value;
312
313   for (midx=0; midx < multipliers.size(); midx++) {
314     Value *= State->GetParameter(multipliers[midx]);
315
316   }
317
318   return Value;
319 }
320
321 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322
323 float FGCoefficient::Value(void)
324 {
325         float Value;
326         unsigned midx;
327
328         Value = StaticValue;
329   Value = (Value + bias)*gain;
330   SD = Value;
331
332   for (midx=0; midx < multipliers.size(); midx++) {
333     Value *= State->GetParameter(multipliers[midx]);
334   }
335
336   return Value;
337 }
338
339 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340
341 float FGCoefficient::TotalValue()
342 {
343   switch(type) {
344   case 0:
345     return -1;
346   case 1:
347     return (Value());
348   case 2:
349     return (Value(State->GetParameter(LookupR)));
350   case 3:
351     return (Value(State->GetParameter(LookupR),State->GetParameter(LookupC)));
352   case 4:
353     return 0.0;
354   }
355   return 0;
356 }
357
358 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359
360 void FGCoefficient::DumpSD(void)
361 {
362   cout << "   " << name << ": " << SD << endl;
363 }
364
365 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366