FlightGear next
FGFilter.cpp
Go to the documentation of this file.
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 Lesser General Public License as published by the Free
11 Software Foundation; either version 2 of the License, or (at your option) any
12 later 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 Lesser General Public License for more
17 details.
18
19 You should have received a copy of the GNU Lesser General Public License along
20 with this program; if not, write to the Free Software Foundation, Inc., 59
21 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Further information about the GNU Lesser General Public License can also be
24 found on the world wide web at http://www.gnu.org.
25
26FUNCTIONAL DESCRIPTION
27--------------------------------------------------------------------------------
28
29HISTORY
30--------------------------------------------------------------------------------
31
32%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33COMMENTS, REFERENCES, and NOTES
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37INCLUDES
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39
40#include "FGFilter.h"
42
43using namespace std;
44
45namespace JSBSim {
46
47/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48CLASS IMPLEMENTATION
49%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50
52 : FGFCSComponent(fcs, element), DynamicFilter(false), Initialize(true)
53{
54 C[1] = C[2] = C[3] = C[4] = C[5] = C[6] = nullptr;
55
56 CheckInputNodes(1, 1, element);
57
58 for (int i=1; i<7; i++)
59 ReadFilterCoefficients(element, i);
60
61 if (Type == "LAG_FILTER") FilterType = eLag ;
62 else if (Type == "LEAD_LAG_FILTER") FilterType = eLeadLag ;
63 else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2 ;
64 else if (Type == "WASHOUT_FILTER") FilterType = eWashout ;
65 else FilterType = eUnknown ;
66
67 CalculateDynamicFilters();
68
69 bind(element);
70
71 Debug(0);
72}
73
74//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
77{
78 Debug(1);
79}
80
81//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82
84{
86
87 Input = 0.0; Initialize = true;
88}
89
90//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91
92void FGFilter::ReadFilterCoefficients(Element* element, int index)
93{
94 // index is known to be 1-7.
95 // A stringstream would be overkill, but also trying to avoid sprintf
96 string coefficient = "c0";
97 coefficient[1] += index;
98
99 if ( element->FindElement(coefficient) ) {
100 C[index] = new FGParameterValue(element->FindElement(coefficient),
102 DynamicFilter |= !C[index]->IsConstant();
103 }
104}
105
106//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107
108void FGFilter::CalculateDynamicFilters(void)
109{
110 double denom;
111
112 switch (FilterType) {
113 case eLag:
114 denom = 2.0 + dt*C[1];
115 ca = dt*C[1] / denom;
116 cb = (2.0 - dt*C[1]) / denom;
117
118 break;
119 case eLeadLag:
120 denom = 2.0*C[3] + dt*C[4];
121 ca = (2.0*C[1] + dt*C[2]) / denom;
122 cb = (dt*C[2] - 2.0*C[1]) / denom;
123 cc = (2.0*C[3] - dt*C[4]) / denom;
124 break;
125 case eOrder2:
126 denom = 4.0*C[4] + 2.0*C[5]*dt + C[6]*dt*dt;
127 ca = (4.0*C[1] + 2.0*C[2]*dt + C[3]*dt*dt) / denom;
128 cb = (2.0*C[3]*dt*dt - 8.0*C[1]) / denom;
129 cc = (4.0*C[1] - 2.0*C[2]*dt + C[3]*dt*dt) / denom;
130 cd = (2.0*C[6]*dt*dt - 8.0*C[4]) / denom;
131 ce = (4.0*C[4] - 2.0*C[5]*dt + C[6]*dt*dt) / denom;
132 break;
133 case eWashout:
134 denom = 2.0 + dt*C[1];
135 ca = 2.0 / denom;
136 cb = (2.0 - dt*C[1]) / denom;
137 break;
138 case eUnknown:
139 cerr << "Unknown filter type" << endl;
140 break;
141 }
142
143}
144
145//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146
148{
149 if (Initialize) {
150
151 PreviousOutput2 = PreviousInput2 = PreviousOutput1 = PreviousInput1 = Output = Input;
152 Initialize = false;
153
154 } else {
155
156 Input = InputNodes[0]->getDoubleValue();
157
158 if (DynamicFilter) CalculateDynamicFilters();
159
160 switch (FilterType) {
161 case eLag:
162 Output = (Input + PreviousInput1) * ca + PreviousOutput1 * cb;
163 break;
164 case eLeadLag:
165 Output = Input * ca + PreviousInput1 * cb + PreviousOutput1 * cc;
166 break;
167 case eOrder2:
168 Output = Input * ca + PreviousInput1 * cb + PreviousInput2 * cc
169 - PreviousOutput1 * cd - PreviousOutput2 * ce;
170 break;
171 case eWashout:
172 Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
173 break;
174 case eUnknown:
175 break;
176 }
177
178 }
179
180 PreviousOutput2 = PreviousOutput1;
181 PreviousOutput1 = Output;
182 PreviousInput2 = PreviousInput1;
183 PreviousInput1 = Input;
184
185 Clip();
186 SetOutput();
187
188 return true;
189}
190
191//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192// The bitmasked value choices are as follows:
193// unset: In this case (the default) JSBSim would only print
194// out the normally expected messages, essentially echoing
195// the config files as they are read. If the environment
196// variable is not set, debug_lvl is set to 1 internally
197// 0: This requests JSBSim not to output any messages
198// whatsoever.
199// 1: This value explicity requests the normal JSBSim
200// startup messages
201// 2: This value asks for a message to be printed out when
202// a class is instantiated
203// 4: When this value is set, a message is displayed when a
204// FGModel object executes its Run() method
205// 8: When this value is set, various runtime state variables
206// are printed out periodically
207// 16: When set various parameters are sanity checked and
208// a message is printed out when they go out of bounds
209
210void FGFilter::Debug(int from)
211{
212 if (debug_lvl <= 0) return;
213
214 if (debug_lvl & 1) { // Standard console startup message output
215 if (from == 0) { // Constructor
216 cout << " INPUT: " << InputNodes[0]->GetName() << endl;
217
218 for (int i=1; i < 7; i++) {
219 if (!C[i]) break;
220
221 cout << " C[" << i << "]";
222 if (!C[i]->IsConstant()) cout << " is the value of property";
223 cout << ": "<< C[i]->GetName() << endl;
224 }
225
226 for (auto node: OutputNodes)
227 cout << " OUTPUT: " << node->getNameString() << endl;
228 }
229 }
230 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
231 if (from == 0) cout << "Instantiated: FGFilter" << endl;
232 if (from == 1) cout << "Destroyed: FGFilter" << endl;
233 }
234 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
235 }
236 if (debug_lvl & 8 ) { // Runtime state variables
237 }
238 if (debug_lvl & 16) { // Sanity checking
239 }
240 if (debug_lvl & 64) {
241 if (from == 0) { // Constructor
242 }
243 }
244}
245}
#define i(x)
Element * FindElement(const std::string &el="")
Searches for a specified element.
FGFCSComponent(FGFCS *fcs, Element *el)
Constructor.
std::vector< FGPropertyValue_ptr > InputNodes
void CheckInputNodes(size_t MinNodes, size_t MaxNodes, Element *el)
virtual void ResetPastStates(void)
FGPropertyManager * PropertyManager
virtual void bind(Element *el)
virtual void SetOutput(void)
std::vector< FGPropertyNode_ptr > OutputNodes
void ResetPastStates(void) override
Definition FGFilter.cpp:83
FGFilter(FGFCS *fcs, Element *element)
Definition FGFilter.cpp:51
bool Run(void) override
Definition FGFilter.cpp:147
static short debug_lvl
Definition FGJSBBase.h:190
Represents a either a real value or a property value.
#define C
short debug_lvl