JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGGain.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGGain.cpp
4  Author: Jon S. Berndt
5  Date started: 4/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 
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
28 
29 HISTORY
30 --------------------------------------------------------------------------------
31 
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES, and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 
40 #include "FGGain.h"
41 #include "math/FGParameterValue.h"
42 #include "math/FGTable.h"
43 
44 using namespace std;
45 
46 namespace JSBSim {
47 
48 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 CLASS IMPLEMENTATION
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51 
52 FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
53 {
54  Gain = nullptr;
55  Table = nullptr;
56  InMin = -1.0;
57  InMax = 1.0;
58  OutMin = OutMax = 0.0;
59 
60  CheckInputNodes(1, 1, element);
61 
62  if (Type == "PURE_GAIN") {
63  if ( !element->FindElement("gain") ) {
64  cerr << element->ReadFrom()
65  << highint << " No GAIN specified (default: 1.0)" << normint
66  << endl;
67  }
68  }
69 
70  Element* gain_element = element->FindElement("gain");
71  if (gain_element)
72  Gain = new FGParameterValue(gain_element, PropertyManager);
73  else
74  Gain = new FGRealValue(1.0);
75 
76  if (Type == "AEROSURFACE_SCALE") {
77  Element* scale_element = element->FindElement("domain");
78  if (scale_element) {
79  if (scale_element->FindElement("max") && scale_element->FindElement("min") )
80  {
81  InMax = scale_element->FindElementValueAsNumber("max");
82  InMin = scale_element->FindElementValueAsNumber("min");
83  }
84  }
85  scale_element = element->FindElement("range");
86  if (!scale_element)
87  throw(string("No range supplied for aerosurface scale component"));
88  if (scale_element->FindElement("max") && scale_element->FindElement("min") )
89  {
90  OutMax = scale_element->FindElementValueAsNumber("max");
91  OutMin = scale_element->FindElementValueAsNumber("min");
92  } else {
93  cerr << scale_element->ReadFrom()
94  << "Maximum and minimum output values must be supplied for the "
95  "aerosurface scale component" << endl;
96  throw("Some inputs are missing.");
97  }
98  ZeroCentered = true;
99  Element* zero_centered = element->FindElement("zero_centered");
100  //ToDo if zero centered, then mins must be <0 and max's must be >0
101  if (zero_centered) {
102  string sZeroCentered = element->FindElementValue("zero_centered");
103  if (sZeroCentered == string("0") || sZeroCentered == string("false")) {
104  ZeroCentered = false;
105  }
106  }
107  }
108 
109  if (Type == "SCHEDULED_GAIN") {
110  if (element->FindElement("table")) {
111  Table = new FGTable(PropertyManager, element->FindElement("table"));
112  } else {
113  cerr << element->ReadFrom()
114  << "A table must be provided for the scheduled gain component"
115  << endl;
116  throw("Some inputs are missing.");
117  }
118  }
119 
120  bind(element);
121 
122  Debug(0);
123 }
124 
125 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 
127 FGGain::~FGGain()
128 {
129  delete Table;
130 
131  Debug(1);
132 }
133 
134 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 
136 bool FGGain::Run(void )
137 {
138  Input = InputNodes[0]->getDoubleValue();
139 
140  if (Type == "PURE_GAIN") { // PURE_GAIN
141 
142  Output = Gain * Input;
143 
144  } else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN
145 
146  double SchedGain = Table->GetValue();
147  Output = Gain * SchedGain * Input;
148 
149  } else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE
150 
151  if (ZeroCentered) {
152  if (Input == 0.0) {
153  Output = 0.0;
154  } else if (Input > 0) {
155  Output = (Input / InMax) * OutMax;
156  } else {
157  Output = (Input / InMin) * OutMin;
158  }
159  } else {
160  Output = OutMin + ((Input - InMin) / (InMax - InMin)) * (OutMax - OutMin);
161  }
162 
163  Output *= Gain->GetValue();
164  }
165 
166  Clip();
167  SetOutput();
168 
169  return true;
170 }
171 
172 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 // The bitmasked value choices are as follows:
174 // unset: In this case (the default) JSBSim would only print
175 // out the normally expected messages, essentially echoing
176 // the config files as they are read. If the environment
177 // variable is not set, debug_lvl is set to 1 internally
178 // 0: This requests JSBSim not to output any messages
179 // whatsoever.
180 // 1: This value explicity requests the normal JSBSim
181 // startup messages
182 // 2: This value asks for a message to be printed out when
183 // a class is instantiated
184 // 4: When this value is set, a message is displayed when a
185 // FGModel object executes its Run() method
186 // 8: When this value is set, various runtime state variables
187 // are printed out periodically
188 // 16: When set various parameters are sanity checked and
189 // a message is printed out when they go out of bounds
190 
191 void FGGain::Debug(int from)
192 {
193  if (debug_lvl <= 0) return;
194 
195  if (debug_lvl & 1) { // Standard console startup message output
196  if (from == 0) { // Constructor
197  cout << " INPUT: " << InputNodes[0]->GetNameWithSign() << endl;
198  cout << " GAIN: " << Gain->GetName() << endl;
199 
200  for (auto node: OutputNodes)
201  cout << " OUTPUT: " << node->getNameString() << endl;
202 
203  if (Type == "AEROSURFACE_SCALE") {
204  cout << " In/Out Mapping:" << endl;
205  cout << " Input MIN: " << InMin << endl;
206  cout << " Input MAX: " << InMax << endl;
207  cout << " Output MIN: " << OutMin << endl;
208  cout << " Output MAX: " << OutMax << endl;
209  }
210  if (Table != 0) {
211  cout << " Scheduled by table: " << endl;
212  Table->Print();
213  }
214  }
215  }
216  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
217  if (from == 0) cout << "Instantiated: FGGain" << endl;
218  if (from == 1) cout << "Destroyed: FGGain" << endl;
219  }
220  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
221  }
222  if (debug_lvl & 8 ) { // Runtime state variables
223  }
224  if (debug_lvl & 16) { // Sanity checking
225  }
226  if (debug_lvl & 64) {
227  if (from == 0) { // Constructor
228  }
229  }
230 }
231 }