]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/filtersjb/FGSwitch.cpp
Rob Deters: UIUC updates from March 1, 2004.
[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   struct FGCondition *current_condition;
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     }
128     AC_cfg->GetNextConfigLine();
129   }
130
131   FGFCSComponent::bind();
132
133   Debug(0);
134 }
135
136 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137
138 FGSwitch::~FGSwitch()
139 {
140   Debug(1);
141 }
142
143 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144
145 bool FGSwitch::Run(void )
146 {
147   vector <test>::iterator iTests = tests.begin();
148   vector <FGCondition>::iterator iConditions;
149   bool pass = false;
150
151   FGFCSComponent::Run(); // call the base class for initialization of Input
152
153   while (iTests < tests.end()) {
154     iConditions = iTests->conditions.begin();
155
156     if (iTests->Logic == eDefault) {
157       Output = iTests->GetValue();
158     } else if (iTests->Logic == eAND) {
159       pass = true;
160       while (iConditions < iTests->conditions.end()) {
161         if (!iConditions->Evaluate()) pass = false;
162         *iConditions++;
163       }
164     } else if (iTests->Logic == eOR) {
165       pass = false;
166       while (iConditions < iTests->conditions.end()) {
167         if (iConditions->Evaluate()) pass = true;
168         *iConditions++;
169       }
170     } else {
171       cerr << "Invalid logic test" << endl;
172     }
173
174     if (pass) {
175       Output = iTests->GetValue();
176       break;
177     }
178     *iTests++;
179   }
180
181   return true;
182 }
183
184 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185 //    The bitmasked value choices are as follows:
186 //    unset: In this case (the default) JSBSim would only print
187 //       out the normally expected messages, essentially echoing
188 //       the config files as they are read. If the environment
189 //       variable is not set, debug_lvl is set to 1 internally
190 //    0: This requests JSBSim not to output any messages
191 //       whatsoever.
192 //    1: This value explicity requests the normal JSBSim
193 //       startup messages
194 //    2: This value asks for a message to be printed out when
195 //       a class is instantiated
196 //    4: When this value is set, a message is displayed when a
197 //       FGModel object executes its Run() method
198 //    8: When this value is set, various runtime state variables
199 //       are printed out periodically
200 //    16: When set various parameters are sanity checked and
201 //       a message is printed out when they go out of bounds
202
203 void FGSwitch::Debug(int from)
204 {
205   vector <test>::iterator iTests = tests.begin();
206   vector <FGCondition>::iterator iConditions;
207   string comp, scratch;
208   string indent = "        ";
209   bool first = false;
210
211   if (debug_lvl <= 0) return;
212
213   if (debug_lvl & 1) { // Standard console startup message output
214     if (from == 0) { // Constructor
215       while (iTests < tests.end()) {
216
217         scratch = " if ";
218
219         switch(iTests->Logic) {
220         case (elUndef):
221           comp = " UNSET ";
222           cerr << "Unset logic for test condition" << endl;
223           break;
224         case (eAND):
225           comp = " AND ";
226           break;
227         case (eOR):
228           comp=" OR ";
229           break;
230         case (eDefault):
231           scratch = " by default.";
232           break;
233         default:
234           comp = " UNKNOWN ";
235           cerr << "Unknown logic for test condition" << endl;
236         }
237
238         if (iTests->OutputProp != 0L)
239           if (iTests->sign < 0)
240             cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
241           else
242             cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
243         else
244           cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
245
246         iConditions = iTests->conditions.begin();
247         first = true;
248         while (iConditions < iTests->conditions.end()) {
249           if (!first) cout << indent << comp << " ";
250           else cout << indent << " ";
251           first = false;
252           iConditions->PrintCondition();
253           cout << endl;
254           *iConditions++;
255         }
256         cout << endl;
257         *iTests++;
258       }
259     }
260   }
261   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
262     if (from == 0) cout << "Instantiated: FGSwitch" << endl;
263     if (from == 1) cout << "Destroyed:    FGSwitch" << endl;
264   }
265   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
266   }
267   if (debug_lvl & 8 ) { // Runtime state variables
268   }
269   if (debug_lvl & 16) { // Sanity checking
270   }
271   if (debug_lvl & 64) {
272     if (from == 0) { // Constructor
273       cout << IdSrc << endl;
274       cout << IdHdr << endl;
275     }
276   }
277 }
278
279 } //namespace JSBSim
280