JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGLinearActuator.cpp
1 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2  *
3 Module: FGLinearActuator.cpp
4 Author: Adriano Bassignana
5 Date started: 2019-01-03
6 
7 ------------- Copyright (C) 2019 Adriano Bassignana -------------
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 
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
28 
29 HISTORY
30 --------------------------------------------------------------------------------
31 
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES, and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 
40 #include "FGLinearActuator.h"
41 #include "math/FGParameterValue.h"
42 
43 using namespace std;
44 
45 namespace JSBSim {
46 
47 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 CLASS IMPLEMENTATION
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50 
51 FGLinearActuator::FGLinearActuator(FGFCS* fcs, Element* element)
52  : FGFCSComponent(fcs, element)
53 {
54  CheckInputNodes(1, 1, element);
55 
56  ptrSet = nullptr;
57  if (element->FindElement("set")) {
58  string property_string = element->FindElementValue("set");
59  ptrSet = new FGParameterValue(property_string, PropertyManager);
60  if (ptrSet && ptrSet->IsConstant()) {
61  set = ptrSet->GetValue() >= 0.5;
62  }
63  }
64 
65  ptrReset = nullptr;
66  if (element->FindElement("reset")) {
67  string property_string = element->FindElementValue("reset");
68  ptrReset = new FGParameterValue(property_string, PropertyManager);
69  if (ptrReset && ptrReset->IsConstant()) {
70  reset = ptrReset->GetValue() >= 0.5;
71  }
72  }
73 
74  ptrVersus = nullptr;
75  if (element->FindElement("versus")) {
76  string property_string = element->FindElementValue("versus");
77  ptrVersus = new FGParameterValue(property_string, PropertyManager);
78  if (ptrVersus && ptrVersus->IsConstant()) {
79  versus = ptrVersus->GetValue();
80  }
81  }
82 
83  ptrBias = nullptr;
84  if (element->FindElement("bias")) {
85  string property_string = element->FindElementValue("bias");
86  ptrBias = new FGParameterValue(property_string, PropertyManager);
87  if (ptrBias && ptrBias->IsConstant()) {
88  bias = ptrBias->GetValue();
89  }
90  }
91 
92  if (element->FindElement("module")) {
93  module = element->FindElementValueAsNumber("module");
94  if (module < 0) {
95  cout << "FGLinearActuator::Run " << InputNodes[0]->GetNameWithSign()
96  << " <module> parameter is forced from " << module
97  << " value to 1.0 value" << endl;
98  module = 1.0;
99  }
100  }
101 
102  if (element->FindElement("hysteresis")) {
103  hysteresis = element->FindElementValueAsNumber("hysteresis");
104  if (hysteresis < 0) {
105  cout << "FGLinearActuator::Run " << InputNodes[0]->GetNameWithSign()
106  << " <hysteresis> parameter is forced from " << hysteresis
107  << " value to 0.0 value" << endl;
108  hysteresis = 0.0;
109  }
110  }
111 
112  if (element->FindElement("lag")) {
113  lag = element->FindElementValueAsNumber("lag");
114  if (lag > 0.0) {
115  double denom = 2.00 + dt*lag;
116  ca = dt * lag / denom;
117  cb = (2.00 - dt * lag) / denom;
118  previousLagInput = previousLagOutput = 0.0;
119  } else {
120  if (lag < 0) {
121  cout << "FGLinearActuator::Run " << InputNodes[0]->GetNameWithSign()
122  << " <lag> parameter is forced from "
123  << lag << " value to 0.0 value" << endl;
124  lag = 0;
125  }
126  }
127  }
128 
129  if (element->FindElement("rate")) {
130  rate = element->FindElementValueAsNumber("rate");
131  if (rate <= 0 || rate > 1.0) {
132  cout << "FGLinearActuator::Run " << InputNodes[0]->GetNameWithSign()
133  << " <rate> parameter is forced from " << rate
134  << " value to 0.5 value" << endl;
135  rate = 0.5;
136  }
137  }
138 
139  if (element->FindElement("gain"))
140  gain = element->FindElementValueAsNumber("gain");
141 
142  bind(element);
143 
144  Debug(0);
145 }
146 
147 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 
150 {
151  Debug(1);
152 }
153 
154 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155 
157 {
158  if (ptrSet && !ptrSet->IsConstant()) set = ptrSet->GetValue() >= 0.5;
159  if (ptrReset && !ptrReset->IsConstant()) reset = ptrReset->GetValue() >= 0.5;
160 
161  if (reset) {
162  inputMem = 0.0;
163  countSpin = 0;
164  direction = 0;
165  Output = 0.0;
166  inputLast = 0.0;
167  } else {
168  if (set) {
169  Input = InputNodes[0]->getDoubleValue() - inputLast;
170  double inputDelta = Input - inputMem;
171  if (abs(inputDelta) >= hysteresis) {
172  if (ptrVersus && !ptrVersus->IsConstant()) {
173  versus = ptrVersus->GetValue();
174  if (versus >= 0.5) {
175  versus = 1;
176  } else if (versus <= -0.5) {
177  versus = -1;
178  } else versus = 0;
179  }
180  if (abs(inputDelta) <= (module * rate)) {
181  if (inputDelta > 0.0) {
182  direction = 1;
183  } else if (inputDelta < 0.0) {
184  direction = -1;
185  }
186  }
187  if ((versus == 0) || (versus == direction)) {
188  inputMem = Input;
189  if (abs(inputDelta) >= (module*rate)) {
190  if (inputDelta < 0)
191  countSpin++;
192  else
193  countSpin--;
194  }
195  } else if ((versus != 0) && (direction != 0) && (versus != direction)) {
196  inputLast += inputDelta;
197  }
198  }
199  }
200  if (ptrBias && !ptrBias->IsConstant()) {
201  bias = ptrBias->GetValue();
202  }
203  Output = gain * (bias + inputMem + module*countSpin);
204  }
205 
206  if (lag > 0.0) {
207  double input = Output;
208  Output = ca * (input + previousLagInput) + previousLagOutput * cb;
209  previousLagInput = input;
210  previousLagOutput = Output;
211  }
212 
213  SetOutput();
214 
215  return true;
216 }
217 
218 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 // The bitmasked value choices are as follows:
220 // unset: In this case (the default) JSBSim would only print
221 // out the normally expected messages, essentially echoing
222 // the config files as they are read. If the environment
223 // variable is not set, debug_lvl is set to 1 internally
224 // 0: This requests JSBSim not to output any messages
225 // whatsoever.
226 // 1: This value explicity requests the normal JSBSim
227 // startup messages
228 // 2: This value asks for a message to be printed out when
229 // a class is instantiated
230 // 4: When this value is set, a message is displayed when a
231 // FGModel object executes its Run() method
232 // 8: When this value is set, various runtime state variables
233 // are printed out periodically
234 // 16: When set various parameters are sanity checked and
235 // a message is printed out when they go out of bounds
236 void FGLinearActuator::Debug(int from)
237 {
238  if (debug_lvl <= 0) return;
239 
240  if (debug_lvl & 1) { // Standard console startup message output
241  if (from == 0) { // Constructor
242  cout << " INPUT: " << InputNodes[0]->GetNameWithSign() << endl;
243  cout << " inputMem: " << inputMem << endl;
244  cout << " bias: " << bias << endl;
245  cout << " module: " << module << endl;
246  cout << " hysteresis: " << hysteresis << endl;
247  cout << " rate: " << rate << endl;
248  cout << " versus: " << versus << endl;
249  cout << " direction: " << direction << endl;
250  cout << " countSpin: " << countSpin << endl;
251  cout << " Lag: " << lag << endl;
252  cout << " Gain: " << gain << endl;
253  cout << " set: " << set << endl;
254  cout << " reset: " << reset << endl;
255  for (auto node: OutputNodes)
256  cout << " OUTPUT: " << node->GetName() << endl;
257  }
258  }
259  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
260  if (from == 0) cout << "Instantiated: FGLinearActuator" << endl;
261  if (from == 1) cout << "Destroyed: FGLinearActuator" << endl;
262  }
263  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
264  }
265  if (debug_lvl & 8 ) { // Runtime state variables
266  }
267  if (debug_lvl & 16) { // Sanity checking
268  }
269  if (debug_lvl & 64) {
270  if (from == 0) { // Constructor
271  }
272  }
273 }
274 }
JSBSim::FGLinearActuator::~FGLinearActuator
~FGLinearActuator()
Destructor.
Definition: FGLinearActuator.cpp:149
JSBSim::Element::FindElement
Element * FindElement(const std::string &el="")
Searches for a specified element.
Definition: FGXMLElement.cpp:389
JSBSim::Element::FindElementValueAsNumber
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
Definition: FGXMLElement.cpp:429
JSBSim::FGFCSComponent
Base class for JSBSim Flight Control System Components.
Definition: FGFCSComponent.h:84
JSBSim::FGLinearActuator::Run
bool Run(void) override
The execution method for this FCS component.
Definition: FGLinearActuator.cpp:156
JSBSim::Element::FindElementValue
std::string FindElementValue(const std::string &el="")
Searches for the named element and returns the string data belonging to it.
Definition: FGXMLElement.cpp:468
JSBSim::FGParameterValue
Represents a either a real value or a property value.
Definition: FGParameterValue.h:63
JSBSim::FGFCS
Encapsulates the Flight Control System (FCS) functionality.
Definition: FGFCS.h:187
JSBSim::Element
Definition: FGXMLElement.h:143