]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/filtersjb/FGSwitch.cpp
Fix stall widths for the "auxilliary" (reverse flow) stalls so they
[flightgear.git] / src / FDM / JSBSim / filtersjb / FGSwitch.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGSwitch.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 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 General Public License for more
17  details.
18
19  You should have received a copy of the GNU 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 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 The SWITCH component is defined as follows (see the API documentation for more
37 information):
38
39 <COMPONENT NAME="switch1" TYPE="SWITCH">
40   <TEST LOGIC="{AND|OR|DEFAULT}" OUTPUT="{property|value}">
41     {property} {conditional} {property|value}
42     <CONDITION_GROUP LOGIC="{AND|OR}">
43       {property} {conditional} {property|value}
44       ...
45     </CONDITION_GROUP>
46     ...
47   </TEST>
48   <TEST LOGIC="{AND|OR}" OUTPUT="{property|value}">
49     {property} {conditional} {property|value}
50     ...
51   </TEST>
52   ...
53 </COMPONENT>
54
55 Also, see the header file (FGSwitch.h) for further details.
56
57 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58 INCLUDES
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
60
61 #include "FGSwitch.h"
62
63 namespace JSBSim {
64
65 static const char *IdSrc = "$Id$";
66 static const char *IdHdr = ID_SWITCH;
67
68 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 CLASS IMPLEMENTATION
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
71
72
73 FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
74                                                        AC_cfg(AC_cfg)
75 {
76   string token, value;
77   struct test *current_test;
78   string sOutputIdx;
79
80   Type = AC_cfg->GetValue("TYPE");
81   Name = AC_cfg->GetValue("NAME");
82
83   AC_cfg->GetNextConfigLine();
84   while ((token = AC_cfg->GetValue()) != string("/COMPONENT")) {
85
86     // See the above documentation, or the API docs, for information on what
87     // the SWITCH component is supposed to look like in the configuration file.
88     // Below, the switch component is read in.
89
90     if (token == "TEST") {
91       tests.push_back(test());
92       current_test = &tests.back();
93
94       if (AC_cfg->GetValue("LOGIC") == "OR") {
95         current_test->Logic = eOR;
96       } else if (AC_cfg->GetValue("LOGIC") == "AND") {
97         current_test->Logic = eAND;
98       } else if (AC_cfg->GetValue("LOGIC") == "DEFAULT") {
99         current_test->Logic = eDefault;
100       } else { // error
101         cerr << "Unrecognized LOGIC token  in switch component: " << Name << endl;
102       }
103
104       value = AC_cfg->GetValue("VALUE");
105       if (value.empty()) {
106         cerr << "No VALUE supplied for switch component: " << Name << endl;
107       } else {
108         if (value.find_first_not_of("-.0123456789eE") == string::npos) {
109           // if true (and execution falls into this block), "value" is a number.
110           current_test->OutputVal = atof(value.c_str());
111         } else {
112           // "value" must be a property if execution passes to here.
113           if (value[0] == '-') {
114             current_test->sign = -1.0;
115             value.erase(0,1);
116           } else {
117             current_test->sign = 1.0;
118           }
119           current_test->OutputProp = PropertyManager->GetNode(value);
120         }
121       }
122
123       AC_cfg->GetNextConfigLine();
124       while (AC_cfg->GetValue() != string("/TEST")) {
125         current_test->conditions.push_back(FGCondition(AC_cfg, PropertyManager));
126       }
127       AC_cfg->GetNextConfigLine();
128     } else if (token == "OUTPUT") {
129       IsOutput = true;
130       *AC_cfg >> sOutputIdx;
131       *AC_cfg >> sOutputIdx;
132       OutputNode = PropertyManager->GetNode( sOutputIdx, true );
133     }
134   }
135
136   FGFCSComponent::bind();
137
138   Debug(0);
139 }
140
141 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142
143 FGSwitch::~FGSwitch()
144 {
145   Debug(1);
146 }
147
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149
150 bool FGSwitch::Run(void )
151 {
152   vector <test>::iterator iTests = tests.begin();
153   vector <FGCondition>::iterator iConditions;
154   bool pass = false;
155
156   FGFCSComponent::Run(); // call the base class for initialization of Input
157
158   while (iTests < tests.end()) {
159     iConditions = iTests->conditions.begin();
160
161     if (iTests->Logic == eDefault) {
162       Output = iTests->GetValue();
163     } else if (iTests->Logic == eAND) {
164       pass = true;
165       while (iConditions < iTests->conditions.end()) {
166         if (!iConditions->Evaluate()) pass = false;
167         *iConditions++;
168       }
169     } else if (iTests->Logic == eOR) {
170       pass = false;
171       while (iConditions < iTests->conditions.end()) {
172         if (iConditions->Evaluate()) pass = true;
173         *iConditions++;
174       }
175     } else {
176       cerr << "Invalid logic test" << endl;
177     }
178
179     if (pass) {
180       Output = iTests->GetValue();
181       break;
182     }
183     *iTests++;
184   }
185
186   if (IsOutput) SetOutput();
187
188   return true;
189 }
190
191 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192
193 void FGSwitch::convert(void)
194 {
195   cout << endl;
196   cout << "        <component name=\"" << Name << "\" type=\"" << Type << "\">" << endl;
197
198 //  cout << "            <input>" << InputNodes[0]->GetName() << "</input>" << endl;
199
200   for (int i=0; i<tests.size(); i++) {
201     if (tests[i].Logic == eDefault) {
202       if (tests[i].OutputProp == 0L)
203         cout << "            <default value=\"" << tests[i].OutputVal << "\"/>" << endl;
204       else
205         cout << "            <default value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\"/>" << endl;
206     } else if (tests[i].Logic == eAND) {
207       if (tests[i].OutputProp == 0L)
208         cout << "            <test logic=\"AND\" value=\"" << tests[i].OutputVal << "\">" << endl;
209       else
210         cout << "            <test logic=\"AND\" value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\">" << endl;
211     } else if (tests[i].Logic == eOR) {
212       if (tests[i].OutputProp == 0L)
213         cout << "            <test logic=\"OR\" value=\"" << tests[i].OutputVal << "\">" << endl;
214       else
215         cout << "            <test logic=\"OR\" value=\"" << (tests[i].OutputProp->GetFullyQualifiedName()).substr(12) << "\">" << endl;
216     }
217     for (int j=0; j<tests[i].conditions.size(); j++) {
218       tests[i].conditions[j].convert();
219     }
220     if (tests[i].Logic != eDefault) cout << "            </test>" << endl;
221   }
222
223   if (IsOutput)
224     cout << "            <output>" << (OutputNode->GetFullyQualifiedName()).substr(12) << "</output>" << endl;
225
226   cout << "        </component>" << endl;
227 }
228
229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230 //    The bitmasked value choices are as follows:
231 //    unset: In this case (the default) JSBSim would only print
232 //       out the normally expected messages, essentially echoing
233 //       the config files as they are read. If the environment
234 //       variable is not set, debug_lvl is set to 1 internally
235 //    0: This requests JSBSim not to output any messages
236 //       whatsoever.
237 //    1: This value explicity requests the normal JSBSim
238 //       startup messages
239 //    2: This value asks for a message to be printed out when
240 //       a class is instantiated
241 //    4: When this value is set, a message is displayed when a
242 //       FGModel object executes its Run() method
243 //    8: When this value is set, various runtime state variables
244 //       are printed out periodically
245 //    16: When set various parameters are sanity checked and
246 //       a message is printed out when they go out of bounds
247
248 void FGSwitch::Debug(int from)
249 {
250   vector <test>::iterator iTests = tests.begin();
251   vector <FGCondition>::iterator iConditions;
252   string comp, scratch;
253   string indent = "        ";
254   bool first = false;
255
256   if (debug_lvl <= 0) return;
257
258   if (debug_lvl & 1) { // Standard console startup message output
259     if (from == 0) { // Constructor
260       while (iTests < tests.end()) {
261
262         scratch = " if ";
263
264         switch(iTests->Logic) {
265         case (elUndef):
266           comp = " UNSET ";
267           cerr << "Unset logic for test condition" << endl;
268           break;
269         case (eAND):
270           comp = " AND ";
271           break;
272         case (eOR):
273           comp=" OR ";
274           break;
275         case (eDefault):
276           scratch = " by default.";
277           break;
278         default:
279           comp = " UNKNOWN ";
280           cerr << "Unknown logic for test condition" << endl;
281         }
282
283         if (iTests->OutputProp != 0L)
284           if (iTests->sign < 0)
285             cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
286           else
287             cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
288         else
289           cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
290
291         iConditions = iTests->conditions.begin();
292         first = true;
293         while (iConditions < iTests->conditions.end()) {
294           if (!first) cout << indent << comp << " ";
295           else cout << indent << " ";
296           first = false;
297           iConditions->PrintCondition();
298           cout << endl;
299           *iConditions++;
300         }
301         cout << endl;
302         *iTests++;
303       }
304       if (IsOutput) cout << "      OUTPUT: " << OutputNode->getName() << endl;
305     }
306   }
307   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
308     if (from == 0) cout << "Instantiated: FGSwitch" << endl;
309     if (from == 1) cout << "Destroyed:    FGSwitch" << endl;
310   }
311   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
312   }
313   if (debug_lvl & 8 ) { // Runtime state variables
314   }
315   if (debug_lvl & 16) { // Sanity checking
316   }
317   if (debug_lvl & 64) {
318     if (from == 0) { // Constructor
319       cout << IdSrc << endl;
320       cout << IdHdr << endl;
321     }
322   }
323 }
324
325 } //namespace JSBSim
326