]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/filtersjb/FGFilter.cpp
Fix stall widths for the "auxilliary" (reverse flow) stalls so they
[flightgear.git] / src / FDM / JSBSim / filtersjb / FGFilter.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGFilter.cpp
4  Author:       Jon S. Berndt
5  Date started: 11/2000
6
7  ------------- Copyright (C) 2000 -------------
8
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  details.
18
19  You should have received a copy of the GNU General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA  02111-1307, USA.
22
23  Further information about the GNU General Public License can also be found on
24  the world wide web at http://www.gnu.org.
25
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
28
29 HISTORY
30 --------------------------------------------------------------------------------
31
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES,  and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39
40 #include "FGFilter.h"
41
42 namespace JSBSim {
43
44 static const char *IdSrc = "$Id$";
45 static const char *IdHdr = ID_FILTER;
46
47 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 CLASS IMPLEMENTATION
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50
51 FGFilter::FGFilter(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
52                                                        AC_cfg(AC_cfg)
53 {
54   string token;
55   double denom;
56   string sOutputIdx;
57
58   Type = AC_cfg->GetValue("TYPE");
59   Name = AC_cfg->GetValue("NAME");
60   AC_cfg->GetNextConfigLine();
61   dt = fcs->GetState()->Getdt();
62   Trigger = 0;
63
64   C1 = C2 = C3 = C4 = C5 = C6 = 0.0;
65
66   if      (Type == "LAG_FILTER")          FilterType = eLag        ;
67   else if (Type == "LEAD_LAG_FILTER")     FilterType = eLeadLag    ;
68   else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2     ;
69   else if (Type == "WASHOUT_FILTER")      FilterType = eWashout    ;
70   else if (Type == "INTEGRATOR")          FilterType = eIntegrator ;
71   else                                    FilterType = eUnknown    ;
72
73   while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
74     *AC_cfg >> token;
75     if (token == "C1")           *AC_cfg >> C1;
76     else if (token == "C2")      *AC_cfg >> C2;
77     else if (token == "C3")      *AC_cfg >> C3;
78     else if (token == "C4")      *AC_cfg >> C4;
79     else if (token == "C5")      *AC_cfg >> C5;
80     else if (token == "C6")      *AC_cfg >> C6;
81     else if (token == "TRIGGER")
82     {
83       token = AC_cfg->GetValue("TRIGGER");
84       *AC_cfg >> token;
85       Trigger =  resolveSymbol(token);
86     }
87     else if (token == "INPUT")
88     {
89       token = AC_cfg->GetValue("INPUT");
90       if( InputNodes.size() > 0 ) {
91         cerr << "Filters can only accept one input" << endl;
92       } else  {
93         *AC_cfg >> token;
94         InputNodes.push_back( resolveSymbol(token) );
95       }
96     }
97     else if (token == "OUTPUT")
98     {
99       IsOutput = true;
100       *AC_cfg >> sOutputIdx;
101       OutputNode = PropertyManager->GetNode( sOutputIdx );
102     }
103     else cerr << "Unknown filter type: " << token << endl;
104   }
105
106   Initialize = true;
107
108   switch (FilterType) {
109     case eLag:
110       denom = 2.00 + dt*C1;
111       ca = dt*C1 / denom;
112       cb = (2.00 - dt*C1) / denom;
113       break;
114     case eLeadLag:
115       denom = 2.00*C3 + dt*C4;
116       ca = (2.00*C1 + dt*C2) / denom;
117       cb = (dt*C2 - 2.00*C1) / denom;
118       cc = (2.00*C3 - dt*C4) / denom;
119       break;
120     case eOrder2:
121       denom = 4.0*C4 + 2.0*C5*dt + C6*dt*dt;
122       ca = (4.0*C1 + 2.0*C2*dt + C3*dt*dt) / denom;
123       cb = (2.0*C3*dt*dt - 8.0*C1) / denom;
124       cc = (4.0*C1 - 2.0*C2*dt + C3*dt*dt) / denom;
125       cd = (2.0*C6*dt*dt - 8.0*C4) / denom;
126       ce = (4.0*C4 - 2.0*C5*dt + C6*dt*dt) / denom;
127       break;
128     case eWashout:
129       denom = 2.00 + dt*C1;
130       ca = 2.00 / denom;
131       cb = (2.00 - dt*C1) / denom;
132       break;
133     case eIntegrator:
134       ca = dt*C1 / 2.00;
135       break;
136     case eUnknown:
137       cerr << "Unknown filter type" << endl;
138     break;
139   }
140   FGFCSComponent::bind();
141
142   Debug(0);
143 }
144
145 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146
147 FGFilter::~FGFilter()
148 {
149   Debug(1);
150 }
151
152 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153
154 bool FGFilter::Run(void)
155 {
156   int test = 0;
157
158   FGFCSComponent::Run(); // call the base class for initialization of Input
159
160   if (Initialize) {
161
162     PreviousOutput1 = PreviousInput1 = Output = Input;
163     Initialize = false;
164
165   } else if (Trigger != 0) {
166     test = Trigger->getIntValue();
167     if (test < 0) {
168       Input  = PreviousInput1 = PreviousInput2 = 0.0;
169     } else {
170       Output = PreviousOutput1 = PreviousOutput2 = 0.0;
171     }
172
173   } else {
174     Input = InputNodes[0]->getDoubleValue();
175     switch (FilterType) {
176       case eLag:
177         Output = Input * ca + PreviousInput1 * ca + PreviousOutput1 * cb;
178         break;
179       case eLeadLag:
180         Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc;
181         break;
182       case eOrder2:
183         Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc
184                             - PreviousOutput1 * cd - PreviousOutput2 * ce;
185         break;
186       case eWashout:
187         Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
188         break;
189       case eIntegrator:
190         Output = Input * ca + PreviousInput1 * ca + PreviousOutput1;
191         break;
192       case eUnknown:
193         break;
194     }
195
196   }
197
198   PreviousOutput2 = PreviousOutput1;
199   PreviousOutput1 = Output;
200   PreviousInput2  = PreviousInput1;
201   PreviousInput1  = Input;
202
203   if (IsOutput) SetOutput();
204
205   return true;
206 }
207
208 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209
210 void FGFilter::convert(void)
211 {
212   cout << endl;
213   cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
214
215   cout << "            <input>" << (InputNodes[0]->GetFullyQualifiedName()).substr(12) << "</input>" << endl;
216
217   if (C1 != 0) cout << "            <c1>" << C1 << "</c1>" << endl;
218   if (C2 != 0) cout << "            <c2>" << C2 << "</c2>" << endl;
219   if (C3 != 0) cout << "            <c3>" << C3 << "</c3>" << endl;
220   if (C4 != 0) cout << "            <c4>" << C4 << "</c4>" << endl;
221   if (C5 != 0) cout << "            <c5>" << C5 << "</c5>" << endl;
222   if (C6 != 0) cout << "            <c6>" << C6 << "</c6>" << endl;
223
224   if (Trigger != 0) cout << "            <trigger>" << Trigger << "</trigger>" << endl;
225
226   if (IsOutput)
227     cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
228
229   cout << "        </component>" << endl;
230 }
231
232 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233 //    The bitmasked value choices are as follows:
234 //    unset: In this case (the default) JSBSim would only print
235 //       out the normally expected messages, essentially echoing
236 //       the config files as they are read. If the environment
237 //       variable is not set, debug_lvl is set to 1 internally
238 //    0: This requests JSBSim not to output any messages
239 //       whatsoever.
240 //    1: This value explicity requests the normal JSBSim
241 //       startup messages
242 //    2: This value asks for a message to be printed out when
243 //       a class is instantiated
244 //    4: When this value is set, a message is displayed when a
245 //       FGModel object executes its Run() method
246 //    8: When this value is set, various runtime state variables
247 //       are printed out periodically
248 //    16: When set various parameters are sanity checked and
249 //       a message is printed out when they go out of bounds
250
251 void FGFilter::Debug(int from)
252 {
253   if (debug_lvl <= 0) return;
254
255   if (debug_lvl & 1) { // Standard console startup message output
256     if (from == 0) { // Constructor
257       cout << "      INPUT: " << InputNodes[0]->getName() << endl;
258       cout << "      C1: " << C1 << endl;
259       cout << "      C2: " << C2 << endl;
260       cout << "      C3: " << C3 << endl;
261       cout << "      C4: " << C4 << endl;
262       cout << "      C5: " << C5 << endl;
263       cout << "      C6: " << C6 << endl;
264       if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
265     }
266   }
267   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
268     if (from == 0) cout << "Instantiated: FGFilter" << endl;
269     if (from == 1) cout << "Destroyed:    FGFilter" << endl;
270   }
271   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
272   }
273   if (debug_lvl & 8 ) { // Runtime state variables
274   }
275   if (debug_lvl & 16) { // Sanity checking
276   }
277   if (debug_lvl & 64) {
278     if (from == 0) { // Constructor
279       cout << IdSrc << endl;
280       cout << IdHdr << endl;
281     }
282   }
283 }
284 }