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