1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 ------------- Copyright (C) 2000 -------------
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
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
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.
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.
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
30 --------------------------------------------------------------------------------
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES, and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 The switch component is defined as follows (see the API documentation for more
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}
50 <test logic="{AND|OR}" value="{property|value}">
51 {property} {conditional} {property|value}
58 Also, see the header file (FGSwitch.h) for further details.
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
72 static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.22 2011/06/17 12:12:19 jberndt Exp $";
73 static const char *IdHdr = ID_SWITCH;
75 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
79 FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
82 struct test *current_test;
83 Element *test_element, *condition_element;
85 FGFCSComponent::bind(); // Bind() this component here in case it is used
86 // in its own definition for a sample-and-hold
88 test_element = element->GetElement();
89 while (test_element) {
90 if (test_element->GetName() == "default") {
91 current_test = new struct test;
92 current_test->Logic = eDefault;
93 tests.push_back(current_test);
94 } else if (test_element->GetName() == "test") { // here's a test
95 current_test = new struct test;
96 logic = test_element->GetAttributeValue("logic");
97 if (logic == "OR") current_test->Logic = eOR;
98 else if (logic == "AND") current_test->Logic = eAND;
99 else if (logic.size() == 0) current_test->Logic = eAND; // default
101 cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl;
103 for (unsigned int i=0; i<test_element->GetNumDataLines(); i++) {
104 string input_data = test_element->GetDataLine(i);
105 if (input_data.size() <= 1) {
106 // Make sure there are no bad data lines that consist solely of whitespace
107 cerr << fgred << " Bad data line in switch component: " << Name << reset << endl;
110 current_test->conditions.push_back(new FGCondition(input_data, PropertyManager));
113 condition_element = test_element->GetElement(); // retrieve condition groups
114 while (condition_element) {
115 current_test->conditions.push_back(new FGCondition(condition_element, PropertyManager));
116 condition_element = test_element->GetNextElement();
119 tests.push_back(current_test);
122 string el_name = test_element->GetName();
123 if ( el_name != "output"
124 && el_name != "description"
125 && el_name != "delay" )
127 value = test_element->GetAttributeValue("value");
129 cerr << "No VALUE supplied for switch component: " << Name << endl;
131 if (is_number(value)) {
132 current_test->OutputVal = atof(value.c_str());
134 // "value" must be a property if execution passes to here.
135 if (value[0] == '-') {
136 current_test->sign = -1.0;
139 current_test->sign = 1.0;
141 FGPropertyManager *node = PropertyManager->GetNode(value, false);
143 current_test->OutputProp = new FGPropertyValue(node);
145 current_test->OutputProp = new FGPropertyValue(value,
151 test_element = element->GetNextElement();
157 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
159 FGSwitch::~FGSwitch()
161 for (unsigned int i=0; i<tests.size(); i++) {
162 for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j];
163 delete tests[i]->OutputProp;
170 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 bool FGSwitch::Run(void )
175 double default_output=0.0;
177 for (unsigned int i=0; i<tests.size(); i++) {
178 if (tests[i]->Logic == eDefault) {
179 default_output = tests[i]->GetValue();
180 } else if (tests[i]->Logic == eAND) {
182 for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
183 if (!tests[i]->conditions[j]->Evaluate()) pass = false;
185 } else if (tests[i]->Logic == eOR) {
187 for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
188 if (tests[i]->conditions[j]->Evaluate()) pass = true;
191 cerr << "Invalid logic test" << endl;
195 Output = tests[i]->GetValue();
200 if (!pass) Output = default_output;
202 if (delay != 0) Delay();
204 if (IsOutput) SetOutput();
209 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 // The bitmasked value choices are as follows:
211 // unset: In this case (the default) JSBSim would only print
212 // out the normally expected messages, essentially echoing
213 // the config files as they are read. If the environment
214 // variable is not set, debug_lvl is set to 1 internally
215 // 0: This requests JSBSim not to output any messages
217 // 1: This value explicity requests the normal JSBSim
219 // 2: This value asks for a message to be printed out when
220 // a class is instantiated
221 // 4: When this value is set, a message is displayed when a
222 // FGModel object executes its Run() method
223 // 8: When this value is set, various runtime state variables
224 // are printed out periodically
225 // 16: When set various parameters are sanity checked and
226 // a message is printed out when they go out of bounds
228 void FGSwitch::Debug(int from)
230 string comp, scratch;
234 if (debug_lvl <= 0) return;
236 if (debug_lvl & 1) { // Standard console startup message output
237 if (from == 0) { // Constructor
238 for (unsigned int i=0; i<tests.size(); i++) {
242 switch(tests[i]->Logic) {
245 cerr << "Unset logic for test condition" << endl;
254 scratch = " by default.";
258 cerr << "Unknown logic for test condition" << endl;
261 if (tests[i]->OutputProp != 0L)
262 if (tests[i]->sign < 0)
263 cout << indent << "Switch VALUE is - " << tests[i]->OutputProp->GetName() << scratch << endl;
265 cout << indent << "Switch VALUE is " << tests[i]->OutputProp->GetName() << scratch << endl;
267 cout << indent << "Switch VALUE is " << tests[i]->OutputVal << scratch << endl;
270 for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
271 if (!first) cout << indent << comp << " ";
272 else cout << indent << " ";
274 tests[i]->conditions[j]->PrintCondition();
280 for (unsigned int i=0; i<OutputNodes.size(); i++)
281 cout << " OUTPUT: " << OutputNodes[i]->getName() << endl;
285 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
286 if (from == 0) cout << "Instantiated: FGSwitch" << endl;
287 if (from == 1) cout << "Destroyed: FGSwitch" << endl;
289 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
291 if (debug_lvl & 8 ) { // Runtime state variables
293 if (debug_lvl & 16) { // Sanity checking
295 if (debug_lvl & 64) {
296 if (from == 0) { // Constructor
297 cout << IdSrc << endl;
298 cout << IdHdr << endl;