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
11 Software Foundation; either version 2 of the License, or (at your option) any
12 later 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
20 with this program; if not, write to the Free Software Foundation, Inc., 59
21 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Further information about the GNU Lesser General Public License can also be
24 found on 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 "math/FGCondition.h"
66
67 using namespace std;
68
69 namespace JSBSim {
70
71 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 CLASS IMPLEMENTATION
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
74
FGSwitch(FGFCS * fcs,Element * element)75 FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
76 {
77 string value;
78 Test *current_test;
79
80 bind(element); // Bind() this component here in case it is used in its own
81 // definition for a sample-and-hold
82 Element* test_element = element->FindElement("default");
83 if (test_element) {
84 current_test = new Test;
85 value = test_element->GetAttributeValue("value");
86 current_test->setTestValue(value, Name, PropertyManager);
87 current_test->Default = true;
88 if (delay > 0 && is_number(value)) { // If there is a delay, initialize the
89 for (unsigned int i=0; i<delay-1; i++) { // delay buffer to the default value
90 output_array[i] = atof(value.c_str()); // for the switch if that value is a number.
91 }
92 }
93 tests.push_back(current_test);
94 }
95
96 test_element = element->FindElement("test");
97 while (test_element) {
98 current_test = new Test;
99 current_test->condition = new FGCondition(test_element, PropertyManager);
100 value = test_element->GetAttributeValue("value");
101 current_test->setTestValue(value, Name, PropertyManager);
102 tests.push_back(current_test);
103 test_element = element->FindNextElement("test");
104 }
105
106 Debug(0);
107 }
108
109 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110
~FGSwitch()111 FGSwitch::~FGSwitch()
112 {
113 for (auto test: tests) {
114 delete test->condition;
115 delete test;
116 }
117
118 Debug(1);
119 }
120
121 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122
Run(void)123 bool FGSwitch::Run(void )
124 {
125 bool pass = false;
126 double default_output=0.0;
127
128 // To detect errors early, make sure all conditions and values can be
129 // evaluated in the first time step.
130 if (!initialized) {
131 initialized = true;
132 VerifyProperties();
133 }
134
135 for (auto test: tests) {
136 if (test->Default) {
137 default_output = test->OutputValue->GetValue();
138 } else {
139 pass = test->condition->Evaluate();
140 }
141
142 if (pass) {
143 Output = test->OutputValue->GetValue();
144 break;
145 }
146 }
147
148 if (!pass) Output = default_output;
149
150 if (delay != 0) Delay();
151 Clip();
152 SetOutput();
153
154 return true;
155 }
156
157 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158
VerifyProperties(void)159 void FGSwitch::VerifyProperties(void)
160 {
161 for (auto test: tests) {
162 if (!test->Default) {
163 test->condition->Evaluate();
164 }
165 test->OutputValue->GetValue();
166 }
167 }
168
169 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 // The bitmasked value choices are as follows:
171 // unset: In this case (the default) JSBSim would only print
172 // out the normally expected messages, essentially echoing
173 // the config files as they are read. If the environment
174 // variable is not set, debug_lvl is set to 1 internally
175 // 0: This requests JSBSim not to output any messages
176 // whatsoever.
177 // 1: This value explicity requests the normal JSBSim
178 // startup messages
179 // 2: This value asks for a message to be printed out when
180 // a class is instantiated
181 // 4: When this value is set, a message is displayed when a
182 // FGModel object executes its Run() method
183 // 8: When this value is set, various runtime state variables
184 // are printed out periodically
185 // 16: When set various parameters are sanity checked and
186 // a message is printed out when they go out of bounds
187
Debug(int from)188 void FGSwitch::Debug(int from)
189 {
190 if (debug_lvl <= 0) return;
191
192 if (debug_lvl & 1) { // Standard console startup message output
193 if (from == 0) { // Constructor
194 unsigned int i = 0;
195 for (auto test: tests) {
196 if (test->Default) {
197 cout << " Switch default value is: " << test->GetOutputName();
198 } else {
199 cout << " Switch takes test " << i << " value (" << test->GetOutputName() << ")" << endl;
200
201 test->condition->PrintCondition(" ");
202 }
203 cout << endl;
204 ++i;
205 }
206 for (auto node: OutputNodes)
207 cout << " OUTPUT: " << node->getName() << endl;
208 }
209 }
210 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
211 if (from == 0) cout << "Instantiated: FGSwitch" << endl;
212 if (from == 1) cout << "Destroyed: FGSwitch" << endl;
213 }
214 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
215 }
216 if (debug_lvl & 8 ) { // Runtime state variables
217 }
218 if (debug_lvl & 16) { // Sanity checking
219 }
220 if (debug_lvl & 64) {
221 if (from == 0) { // Constructor
222 }
223 }
224 }
225
226 } //namespace JSBSim
227
228