FlightGear next
FGLinearActuator.cpp
Go to the documentation of this file.
1/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 *
3Module: FGLinearActuator.cpp
4Author: Adriano Bassignana
5Date started: 2019-01-03
6
7------------- Copyright (C) 2019 Adriano Bassignana -------------
8
9This program is free software; you can redistribute it and/or modify it under
10the terms of the GNU Lesser General Public License as published by the Free
11Software Foundation; either version 2 of the License, or (at your option) any
12later version.
13
14This program is distributed in the hope that it will be useful, but WITHOUT
15ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17details.
18
19You should have received a copy of the GNU Lesser General Public License along
20with this program; if not, write to the Free Software Foundation, Inc., 59
21Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23Further information about the GNU Lesser General Public License can also be
24found 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 "FGLinearActuator.h"
42
43using namespace std;
44
45namespace JSBSim {
46
47/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48CLASS IMPLEMENTATION
49%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50
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
236void 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}
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
std::string FindElementValue(const std::string &el="")
Searches for the named element and returns the string data belonging to it.
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)
FGPropertyManager * PropertyManager
virtual void bind(Element *el)
virtual void SetOutput(void)
std::vector< FGPropertyNode_ptr > OutputNodes
static short debug_lvl
Definition FGJSBBase.h:190
bool Run(void) override
The execution method for this FCS component.
FGLinearActuator(FGFCS *fcs, Element *element)
Constructor.
Represents a either a real value or a property value.
short debug_lvl