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