1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 Date started: 8/25/2004
6 Purpose: Stores various parameter types for functions
8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
14 #include "FGFunction.h"
16 #include "FGPropertyValue.h"
17 #include "FGRealValue.h"
21 static const char *IdSrc = "$Id$";
22 static const char *IdHdr = ID_FUNCTION;
24 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
26 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
28 FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, string prefix)
29 : PropertyManager(propMan), Prefix(prefix)
33 string operation, property_name;
34 int size = el->GetNumElements();
36 cachedValue = -HUGE_VAL;
38 Name = el->GetAttributeValue("name");
39 operation = el->GetName();
40 if (operation == string("function")) {
43 } else if (operation == string("product")) {
45 } else if (operation == string("difference")) {
47 } else if (operation == string("sum")) {
49 } else if (operation == string("quotient")) {
51 } else if (operation == string("pow")) {
53 } else if (operation == string("abs")) {
55 } else if (operation == string("sin")) {
57 } else if (operation == string("cos")) {
59 } else if (operation == string("tan")) {
61 } else if (operation == string("asin")) {
63 } else if (operation == string("acos")) {
65 } else if (operation == string("atan")) {
67 } else if (operation == string("atan2")) {
69 } else if (operation != string("description")) {
70 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
73 element = el->GetElement();
75 operation = element->GetName();
78 if (operation == string("property")) {
79 property_name = element->GetDataLine();
80 FGPropertyManager* newNode = PropertyManager->GetNode(property_name);
82 cerr << "The property " << property_name << " is undefined." << endl;
85 Parameters.push_back(new FGPropertyValue( newNode ));
87 } else if (operation == string("value")) {
88 Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
89 } else if (operation == string("table")) {
90 Parameters.push_back(new FGTable(PropertyManager, element));
92 } else if (operation == string("product") ||
93 operation == string("difference") ||
94 operation == string("sum") ||
95 operation == string("quotient") ||
96 operation == string("pow") ||
97 operation == string("abs") ||
98 operation == string("sin") ||
99 operation == string("cos") ||
100 operation == string("tan") ||
101 operation == string("asin") ||
102 operation == string("acos") ||
103 operation == string("atan") ||
104 operation == string("atan2"))
106 Parameters.push_back(new FGFunction(PropertyManager, element));
107 } else if (operation != string("description")) {
108 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
110 element = el->GetNextElement();
116 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118 FGFunction::~FGFunction(void)
120 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
121 PropertyManager->Untie(tmp);
124 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 void FGFunction::cacheValue(bool cache)
128 cached = false; // Must set cached to false prior to calling GetValue(), else
129 // it will _never_ calculate the value;
131 cachedValue = GetValue();
136 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 double FGFunction::GetValue(void) const
142 if (cached) return cachedValue;
144 double temp = Parameters[0]->GetValue();
150 for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
153 for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
156 for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
159 temp /= Parameters[1]->GetValue();
162 temp = pow(temp,Parameters[1]->GetValue());
186 temp = atan2(temp, Parameters[1]->GetValue());
189 cerr << "Unknown function operation type" << endl;
196 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 string FGFunction::GetValueAsString(void) const
203 sprintf(buffer,"%9.6f",GetValue());
204 value = string(buffer);
208 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 void FGFunction::bind(void)
212 if ( !Name.empty() ) {
213 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
214 PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
218 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 // The bitmasked value choices are as follows:
220 // unset: In this case (the default) JSBSim would only print
221 // out the normally expected messages, essentially echoing
222 // the config files as they are read. If the environment
223 // variable is not set, debug_lvl is set to 1 internally
224 // 0: This requests JSBSim not to output any messages
226 // 1: This value explicity requests the normal JSBSim
228 // 2: This value asks for a message to be printed out when
229 // a class is instantiated
230 // 4: When this value is set, a message is displayed when a
231 // FGModel object executes its Run() method
232 // 8: When this value is set, various runtime state variables
233 // are printed out periodically
234 // 16: When set various parameters are sanity checked and
235 // a message is printed out when they go out of bounds
237 void FGFunction::Debug(int from)
239 if (debug_lvl <= 0) return;
241 if (debug_lvl & 1) { // Standard console startup message output
242 if (from == 0) { // Constructor
243 if (Type == eTopLevel)
244 cout << " Function: " << Name << endl;
247 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
248 if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
249 if (from == 1) cout << "Destroyed: FGGroundReactions" << endl;
251 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
253 if (debug_lvl & 8 ) { // Runtime state variables
255 if (debug_lvl & 16) { // Sanity checking
257 if (debug_lvl & 64) {
258 if (from == 0) { // Constructor
259 cout << IdSrc << endl;
260 cout << IdHdr << endl;