Branch data Line data Source code
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 : : #include <iostream>
66 : : #include <cstdlib>
67 : :
68 : : using namespace std;
69 : :
70 : : namespace JSBSim {
71 : :
72 : : static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.19 2009/10/24 22:59:30 jberndt Exp $";
73 : : static const char *IdHdr = ID_SWITCH;
74 : :
75 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 : : CLASS IMPLEMENTATION
77 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
78 : :
79 : 14 : FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
80 : : {
81 : 14 : string value, logic;
82 : : struct test *current_test;
83 : : Element *test_element, *condition_element;
84 : :
85 : 14 : FGFCSComponent::bind(); // Bind() this component here in case it is used
86 : : // in its own definition for a sample-and-hold
87 : :
88 : 14 : test_element = element->GetElement();
89 [ + + ][ # # ]: 50 : while (test_element) {
90 [ + + # # ]: 36 : if (test_element->GetName() == "default") {
91 : 14 : current_test = new struct test;
92 : 14 : current_test->Logic = eDefault;
93 : 14 : tests.push_back(current_test);
94 [ + + # # ]: 22 : } else if (test_element->GetName() == "test") { // here's a test
95 : 21 : current_test = new struct test;
96 : 42 : logic = test_element->GetAttributeValue("logic");
97 [ + + ][ # # ]: 21 : if (logic == "OR") current_test->Logic = eOR;
98 [ - + ][ # # ]: 18 : else if (logic == "AND") current_test->Logic = eAND;
99 [ + - ][ # # ]: 18 : else if (logic.size() == 0) current_test->Logic = eAND; // default
100 : : else { // error
101 : 0 : cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl;
102 : : }
103 [ + + ][ # # ]: 50 : for (unsigned int i=0; i<test_element->GetNumDataLines(); i++) {
104 : 29 : string input_data = test_element->GetDataLine(i);
105 [ - + # # ]: 29 : if (input_data.size() <= 1) {
106 : : // Make sure there are no bad data lines that consist solely of whitespace
107 : 0 : cerr << fgred << " Bad data line in switch component: " << Name << reset << endl;
108 : : continue;
109 : : }
110 : 29 : current_test->conditions.push_back(new FGCondition(input_data, PropertyManager));
111 : : }
112 : :
113 : 21 : condition_element = test_element->GetElement(); // retrieve condition groups
114 [ - + ][ # # ]: 21 : while (condition_element) {
115 : 0 : current_test->conditions.push_back(new FGCondition(condition_element, PropertyManager));
116 : 0 : condition_element = test_element->GetNextElement();
117 : : }
118 : :
119 : 21 : tests.push_back(current_test);
120 : : }
121 : :
122 [ + + + - ]: 71 : if (test_element->GetName() != "output"
[ + + # #
# # ][ # # ]
123 : : && test_element->GetName() != "description") { // this is not an output element
124 : 70 : value = test_element->GetAttributeValue("value");
125 [ - + # # ]: 35 : if (value.empty()) {
126 : 0 : cerr << "No VALUE supplied for switch component: " << Name << endl;
127 : : } else {
128 [ + + ][ # # ]: 35 : if (is_number(value)) {
129 : 27 : current_test->OutputVal = atof(value.c_str());
130 : : } else {
131 : : // "value" must be a property if execution passes to here.
132 [ - + # # ]: 8 : if (value[0] == '-') {
133 : 0 : current_test->sign = -1.0;
134 : 0 : value.erase(0,1);
135 : : } else {
136 : 8 : current_test->sign = 1.0;
137 : : }
138 : 8 : current_test->OutputProp = PropertyManager->GetNode(value);
139 : : }
140 : : }
141 : : }
142 : 36 : test_element = element->GetNextElement();
143 : : }
144 : :
145 : 14 : Debug(0);
146 : 14 : }
147 : :
148 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 : :
150 : 14 : FGSwitch::~FGSwitch()
151 : : {
152 [ + + ][ # # ]: 49 : for (unsigned int i=0; i<tests.size(); i++) {
[ # # ]
153 [ + - ][ + + ]: 64 : for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j];
[ # # ][ # # ]
[ # # ][ # # ]
154 [ + - ][ # # ]: 35 : delete tests[i];
[ # # ]
155 : : }
156 : :
157 : 14 : Debug(1);
158 [ + - ][ # # ]: 14 : }
[ # # ]
159 : :
160 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161 : :
162 : 756070 : bool FGSwitch::Run(void )
163 : : {
164 : 756070 : bool pass = false;
165 : 756070 : double default_output=0.0;
166 : :
167 [ + + ]: 1666793 : for (unsigned int i=0; i<tests.size(); i++) {
168 [ + + ]: 1556830 : if (tests[i]->Logic == eDefault) {
169 : 756070 : default_output = tests[i]->GetValue();
170 [ + + ]: 800760 : } else if (tests[i]->Logic == eAND) {
171 : 676621 : pass = true;
172 [ + + ]: 1461252 : for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
173 [ + + ]: 784631 : if (!tests[i]->conditions[j]->Evaluate()) pass = false;
174 : : }
175 [ + - ]: 124139 : } else if (tests[i]->Logic == eOR) {
176 : 124139 : pass = false;
177 [ + + ]: 534432 : for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
178 [ + + ]: 410293 : if (tests[i]->conditions[j]->Evaluate()) pass = true;
179 : : }
180 : : } else {
181 : 0 : cerr << "Invalid logic test" << endl;
182 : : }
183 : :
184 [ + + ]: 1556830 : if (pass) {
185 : 1938321 : Output = tests[i]->GetValue();
186 : 646107 : break;
187 : : }
188 : : }
189 : :
190 [ + + ]: 756070 : if (!pass) Output = default_output;
191 : :
192 : 756070 : Clip();
193 [ + + ]: 756070 : if (IsOutput) SetOutput();
194 : :
195 : 756070 : return true;
196 : : }
197 : :
198 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199 : : // The bitmasked value choices are as follows:
200 : : // unset: In this case (the default) JSBSim would only print
201 : : // out the normally expected messages, essentially echoing
202 : : // the config files as they are read. If the environment
203 : : // variable is not set, debug_lvl is set to 1 internally
204 : : // 0: This requests JSBSim not to output any messages
205 : : // whatsoever.
206 : : // 1: This value explicity requests the normal JSBSim
207 : : // startup messages
208 : : // 2: This value asks for a message to be printed out when
209 : : // a class is instantiated
210 : : // 4: When this value is set, a message is displayed when a
211 : : // FGModel object executes its Run() method
212 : : // 8: When this value is set, various runtime state variables
213 : : // are printed out periodically
214 : : // 16: When set various parameters are sanity checked and
215 : : // a message is printed out when they go out of bounds
216 : :
217 : 28 : void FGSwitch::Debug(int from)
218 : : {
219 : 28 : string comp, scratch;
220 : 28 : string indent = " ";
221 : 28 : bool first = false;
222 : :
223 [ + - ]: 28 : if (debug_lvl <= 0) return;
224 : :
225 [ + - ]: 28 : if (debug_lvl & 1) { // Standard console startup message output
226 [ + + ]: 28 : if (from == 0) { // Constructor
227 [ + + ]: 49 : for (unsigned int i=0; i<tests.size(); i++) {
228 : :
229 : : scratch = " if ";
230 : :
231 [ - + + + : 35 : switch(tests[i]->Logic) {
- ]
232 : : case (elUndef):
233 : : comp = " UNSET ";
234 : 0 : cerr << "Unset logic for test condition" << endl;
235 : : break;
236 : : case (eAND):
237 : : comp = " AND ";
238 : : break;
239 : : case (eOR):
240 : : comp=" OR ";
241 : : break;
242 : : case (eDefault):
243 : : scratch = " by default.";
244 : : break;
245 : : default:
246 : : comp = " UNKNOWN ";
247 : 0 : cerr << "Unknown logic for test condition" << endl;
248 : : }
249 : :
250 [ + + ]: 35 : if (tests[i]->OutputProp != 0L)
251 [ - + ]: 8 : if (tests[i]->sign < 0)
252 : 0 : cout << indent << "Switch VALUE is - " << tests[i]->OutputProp->GetName() << scratch << endl;
253 : : else
254 : 16 : cout << indent << "Switch VALUE is " << tests[i]->OutputProp->GetName() << scratch << endl;
255 : : else
256 : 54 : cout << indent << "Switch VALUE is " << tests[i]->OutputVal << scratch << endl;
257 : :
258 : 35 : first = true;
259 [ + + ]: 64 : for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
260 [ + + ]: 29 : if (!first) cout << indent << comp << " ";
261 : 21 : else cout << indent << " ";
262 : 29 : first = false;
263 : 29 : tests[i]->conditions[j]->PrintCondition();
264 : : cout << endl;
265 : : }
266 : : cout << endl;
267 : : }
268 [ + + ]: 14 : if (IsOutput) {
269 [ + + ]: 2 : for (unsigned int i=0; i<OutputNodes.size(); i++)
270 : 1 : cout << " OUTPUT: " << OutputNodes[i]->getName() << endl;
271 : : }
272 : : }
273 : : }
274 [ - + ]: 28 : if (debug_lvl & 2 ) { // Instantiation/Destruction notification
275 [ # # ]: 0 : if (from == 0) cout << "Instantiated: FGSwitch" << endl;
276 [ # # ]: 0 : if (from == 1) cout << "Destroyed: FGSwitch" << endl;
277 : : }
278 : 28 : if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
279 : : }
280 : 28 : if (debug_lvl & 8 ) { // Runtime state variables
281 : : }
282 : 28 : if (debug_lvl & 16) { // Sanity checking
283 : : }
284 [ - + ]: 28 : if (debug_lvl & 64) {
285 [ # # ]: 0 : if (from == 0) { // Constructor
286 : 0 : cout << IdSrc << endl;
287 : 0 : cout << IdHdr << endl;
288 : : }
289 : 28 : }
290 : : }
291 : :
292 [ + + ][ + - ]: 12 : } //namespace JSBSim
293 : :
|