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 Parameters.push_back(new FGPropertyValue(PropertyManager->GetNode(property_name)));
81 } else if (operation == string("value")) {
82 Parameters.push_back(new FGRealValue(element->GetDataAsNumber()));
83 } else if (operation == string("table")) {
84 Parameters.push_back(new FGTable(PropertyManager, element));
86 } else if (operation == string("product") ||
87 operation == string("difference") ||
88 operation == string("sum") ||
89 operation == string("quotient") ||
90 operation == string("pow") ||
91 operation == string("abs") ||
92 operation == string("sin") ||
93 operation == string("cos") ||
94 operation == string("tan") ||
95 operation == string("asin") ||
96 operation == string("acos") ||
97 operation == string("atan") ||
98 operation == string("atan2"))
100 Parameters.push_back(new FGFunction(PropertyManager, element));
101 } else if (operation != string("description")) {
102 cerr << "Bad operation " << operation << " detected in configuration file" << endl;
104 element = el->GetNextElement();
110 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 FGFunction::~FGFunction(void)
114 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
115 PropertyManager->Untie(tmp);
118 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 void FGFunction::cacheValue(bool cache)
122 cached = false; // Must set cached to false prior to calling GetValue(), else
123 // it will _never_ calculate the value;
125 cachedValue = GetValue();
130 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132 double FGFunction::GetValue(void) const
136 if (cached) return cachedValue;
138 double temp = Parameters[0]->GetValue();
144 for (i=1;i<Parameters.size();i++) temp *= Parameters[i]->GetValue();
147 for (i=1;i<Parameters.size();i++) temp -= Parameters[i]->GetValue();
150 for (i=1;i<Parameters.size();i++) temp += Parameters[i]->GetValue();
153 temp /= Parameters[1]->GetValue();
156 temp = pow(temp,Parameters[1]->GetValue());
180 temp = atan2(temp, Parameters[1]->GetValue());
183 cerr << "Unknown function operation type" << endl;
190 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 string FGFunction::GetValueAsString(void) const
197 sprintf(buffer,"%9.6f",GetValue());
198 value = string(buffer);
202 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 void FGFunction::bind(void)
206 if ( !Name.empty() ) {
207 string tmp = PropertyManager->mkPropertyName(Prefix + Name, false); // Allow upper case
208 PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
212 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213 // The bitmasked value choices are as follows:
214 // unset: In this case (the default) JSBSim would only print
215 // out the normally expected messages, essentially echoing
216 // the config files as they are read. If the environment
217 // variable is not set, debug_lvl is set to 1 internally
218 // 0: This requests JSBSim not to output any messages
220 // 1: This value explicity requests the normal JSBSim
222 // 2: This value asks for a message to be printed out when
223 // a class is instantiated
224 // 4: When this value is set, a message is displayed when a
225 // FGModel object executes its Run() method
226 // 8: When this value is set, various runtime state variables
227 // are printed out periodically
228 // 16: When set various parameters are sanity checked and
229 // a message is printed out when they go out of bounds
231 void FGFunction::Debug(int from)
233 if (debug_lvl <= 0) return;
235 if (debug_lvl & 1) { // Standard console startup message output
236 if (from == 0) { // Constructor
237 if (Type == eTopLevel)
238 cout << " Function: " << Name << endl;
241 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
242 if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
243 if (from == 1) cout << "Destroyed: FGGroundReactions" << endl;
245 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
247 if (debug_lvl & 8 ) { // Runtime state variables
249 if (debug_lvl & 16) { // Sanity checking
251 if (debug_lvl & 64) {
252 if (from == 0) { // Constructor
253 cout << IdSrc << endl;
254 cout << IdHdr << endl;