]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/models/flight_control/FGActuator.cpp
sync. with JSBSim CVS again
[flightgear.git] / src / FDM / JSBSim / models / flight_control / FGActuator.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGActuator.cpp
4  Author:       Jon Berndt
5  Date started: 21 February 2006
6
7  ------------- Copyright (C) 2007 Jon S. Berndt (jon@jsbsim.org) -------------
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 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 Lesser General Public License for more
17  details.
18
19  You should have received a copy of the GNU Lesser 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 Lesser 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 "FGActuator.h"
41
42 namespace JSBSim {
43
44 static const char *IdSrc = "$Id$";
45 static const char *IdHdr = ID_ACTUATOR;
46
47 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 CLASS IMPLEMENTATION
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50
51
52 FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
53 {
54   double denom;
55
56   // inputs are read from the base class constructor
57
58   PreviousOutput = 0.0;
59   PreviousHystOutput = 0.0;
60   PreviousRateLimOutput = 0.0;
61   PreviousLagInput = PreviousLagOutput = 0.0;
62   bias = lag = hysteresis_width = deadband_width = 0.0;
63   rate_limit = 0.0; // no limit
64   fail_zero = fail_hardover = fail_stuck = false;
65   ca = cb = 0.0;
66
67   if ( element->FindElement("deadband_width") ) {
68     deadband_width = element->FindElementValueAsNumber("deadband_width");
69   }
70   if ( element->FindElement("hysteresis_width") ) {
71     hysteresis_width = element->FindElementValueAsNumber("hysteresis_width");
72   }
73   if ( element->FindElement("rate_limit") ) {
74     rate_limit = element->FindElementValueAsNumber("rate_limit");
75   }
76   if ( element->FindElement("bias") ) {
77     bias = element->FindElementValueAsNumber("bias");
78   }
79   if ( element->FindElement("lag") ) {
80     lag = element->FindElementValueAsNumber("lag");
81     denom = 2.00 + dt*lag;
82     ca = dt*lag / denom;
83     cb = (2.00 - dt*lag) / denom;
84   }
85
86   FGFCSComponent::bind();
87   bind();
88
89   Debug(0);
90 }
91
92 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93
94 FGActuator::~FGActuator()
95 {
96   Debug(1);
97 }
98
99 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100
101 bool FGActuator::Run(void )
102 {
103   Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
104
105   if (fail_zero) Input = 0;
106   if (fail_hardover) Input =  clipmax*sign(Input);
107
108   Output = Input; // Perfect actuator. At this point, if no failures are present
109                   // and no subsequent lag, limiting, etc. is done, the output
110                   // is simply the input. If any further processing is done
111                   // (below) such as lag, rate limiting, hysteresis, etc., then
112                   // the Input will be further processed and the eventual Output
113                   // will be overwritten from this perfect value.
114
115   if (lag != 0.0)              Lag();        // models actuator lag
116   if (rate_limit != 0)         RateLimit();  // limit the actuator rate
117   if (deadband_width != 0.0)   Deadband();
118   if (hysteresis_width != 0.0) Hysteresis();
119   if (bias != 0.0)             Bias();       // models a finite bias
120
121   if (fail_stuck) Output = PreviousOutput;
122   PreviousOutput = Output; // previous value needed for "stuck" malfunction
123
124   Clip();
125   if (IsOutput) SetOutput();
126
127   return true;
128 }
129
130 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131
132 void FGActuator::Bias(void)
133 {
134   Output += bias;
135 }
136
137 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138
139 void FGActuator::Lag(void)
140 {
141   // "Output" on the right side of the "=" is the current frame input
142   // for this Lag filter
143   double input = Output;
144   Output = ca * (input + PreviousLagInput) + PreviousLagOutput * cb;
145   PreviousLagInput = input;
146   PreviousLagOutput = Output;
147 }
148
149 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150
151 void FGActuator::Hysteresis(void)
152 {
153   // Note: this function acts cumulatively on the "Output" parameter. So, "Output"
154   // is - for the purposes of this Hysteresis method - really the input to the
155   // method.
156   double input = Output;
157   
158   if (input > PreviousHystOutput) {
159     Output = max(PreviousHystOutput, input-0.5*hysteresis_width);
160   } else if (input < PreviousHystOutput) {
161     Output = min(PreviousHystOutput, input+0.5*hysteresis_width);
162   }
163
164   PreviousHystOutput = Output;
165 }
166
167 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168
169 void FGActuator::RateLimit(void)
170 {
171   // Note: this function acts cumulatively on the "Output" parameter. So, "Output"
172   // is - for the purposes of this RateLimit method - really the input to the
173   // method.
174   double input = Output;
175   if (dt > 0.0) {
176     double rate = (input - PreviousRateLimOutput)/dt;
177     if (fabs(rate) > rate_limit) {
178       Output = PreviousRateLimOutput + (rate_limit*fabs(rate)/rate)*dt;
179     }
180   }
181   PreviousRateLimOutput = Output;
182 }
183
184 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185
186 void FGActuator::Deadband(void)
187 {
188 }
189
190 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191
192 void FGActuator::bind(void)
193 {
194   string tmp = Name;
195   if (Name.find("/") == string::npos) {
196     tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
197   }
198   const string tmp_zero = tmp + "/malfunction/fail_zero";
199   const string tmp_hardover = tmp + "/malfunction/fail_hardover";
200   const string tmp_stuck = tmp + "/malfunction/fail_stuck";
201
202   PropertyManager->Tie( tmp_zero, this, &FGActuator::GetFailZero, &FGActuator::SetFailZero);
203   PropertyManager->Tie( tmp_hardover, this, &FGActuator::GetFailHardover, &FGActuator::SetFailHardover);
204   PropertyManager->Tie( tmp_stuck, this, &FGActuator::GetFailStuck, &FGActuator::SetFailStuck);
205 }
206
207 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208 //    The bitmasked value choices are as follows:
209 //    unset: In this case (the default) JSBSim would only print
210 //       out the normally expected messages, essentially echoing
211 //       the config files as they are read. If the environment
212 //       variable is not set, debug_lvl is set to 1 internally
213 //    0: This requests JSBSim not to output any messages
214 //       whatsoever.
215 //    1: This value explicity requests the normal JSBSim
216 //       startup messages
217 //    2: This value asks for a message to be printed out when
218 //       a class is instantiated
219 //    4: When this value is set, a message is displayed when a
220 //       FGModel object executes its Run() method
221 //    8: When this value is set, various runtime state variables
222 //       are printed out periodically
223 //    16: When set various parameters are sanity checked and
224 //       a message is printed out when they go out of bounds
225
226 void FGActuator::Debug(int from)
227 {
228   if (debug_lvl <= 0) return;
229
230   if (debug_lvl & 1) { // Standard console startup message output
231     if (from == 0) { // Constructor
232       if (InputSigns[0] < 0)
233         cout << "      INPUT: -" << InputNodes[0]->getName() << endl;
234       else
235         cout << "      INPUT: " << InputNodes[0]->getName() << endl;
236
237       if (IsOutput) {
238         for (unsigned int i=0; i<OutputNodes.size(); i++)
239           cout << "      OUTPUT: " << OutputNodes[i]->getName() << endl;
240       }
241       if (bias != 0.0) cout << "      Bias: " << bias << endl;
242       if (rate_limit != 0) cout << "      Rate limit: " << rate_limit << endl;
243       if (lag != 0) cout << "      Actuator lag: " << lag << endl;
244       if (hysteresis_width != 0) cout << "      Hysteresis width: " << hysteresis_width << endl;
245       if (deadband_width != 0) cout << "      Deadband width: " << deadband_width << endl;
246     }
247   }
248   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
249     if (from == 0) cout << "Instantiated: FGActuator" << endl;
250     if (from == 1) cout << "Destroyed:    FGActuator" << endl;
251   }
252   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
253   }
254   if (debug_lvl & 8 ) { // Runtime state variables
255   }
256   if (debug_lvl & 16) { // Sanity checking
257   }
258   if (debug_lvl & 64) {
259     if (from == 0) { // Constructor
260       cout << IdSrc << endl;
261       cout << IdHdr << endl;
262     }
263   }
264 }
265 }