]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGXMLElement.cpp
Add support for squared damping coefficients for gears.
[flightgear.git] / src / FDM / JSBSim / input_output / FGXMLElement.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Author:       Jon Berndt
4  Date started: 09/28/2004
5  Purpose:      XML element class
6  Called by:    FGXMLParse
7
8  ------------- Copyright (C) 2001  Jon S. Berndt (jsb@hal-pc.org) -------------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
18  details.
19
20  You should have received a copy of the GNU Lesser General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU Lesser General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 INCLUDES
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31 #include "FGXMLElement.h"
32
33 #include <cmath>
34 #include <cstdlib>
35
36 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 FORWARD DECLARATIONS
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39
40 namespace JSBSim {
41
42 static const char *IdSrc = "$Id$";
43 static const char *IdHdr = ID_XMLELEMENT;
44
45 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
46 CLASS IMPLEMENTATION
47 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
48
49 Element::Element(string nm)
50 {
51   name   = nm;
52   parent = 0L;
53   element_index = 0;
54
55   // convert ["from"]["to"] = factor, so: from * factor = to
56   // Length
57   convert["M"]["FT"] = 3.2808399;
58   convert["FT"]["M"] = 1.0/convert["M"]["FT"];
59   convert["FT"]["IN"] = 12.0;
60   convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
61   convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
62   convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"];
63   // Area
64   convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
65   convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
66   convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"];
67   convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"];
68   // Volume
69   convert["IN3"]["CC"] = 16.387064;
70   convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"];
71   convert["FT3"]["IN3"] = 1728.0;
72   convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"];
73   convert["M3"]["FT3"] = 35.3146667;
74   convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"];
75   convert["LTR"]["IN3"] = 61.0237441;
76   convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"];
77   // Mass & Weight
78   convert["LBS"]["KG"] = 0.45359237;
79   convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
80   convert["SLUG"]["KG"] = 14.59390;
81   convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"];
82   // Moments of Inertia
83   convert["SLUG*FT2"]["KG*M2"] = 1.35594;
84   convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
85   // Angles
86   convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
87   convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
88   // Spring force
89   convert["LBS/FT"]["N/M"] = 14.5939;
90   convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
91   // Damping force
92   convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
93   convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
94   // Damping force (Square Law)
95   convert["LBS/FT/SEC2"]["N/M/SEC2"] = 14.5939;
96   convert["N/M/SEC2"]["LBS/FT/SEC2"] = 1.0/convert["LBS/FT/SEC2"]["N/M/SEC2"];
97   // Power
98   convert["WATTS"]["HP"] = 0.001341022;
99   convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
100   // Force
101   convert["N"]["LBS"] = 0.22482;
102   convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
103   // Velocity
104   convert["KTS"]["FT/SEC"] = 1.68781;
105   convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
106   convert["M/S"]["FT/S"] = 3.2808399;
107   convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
108   // Torque
109   convert["FT*LBS"]["N*M"] = 1.35581795;
110   convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
111   // Valve
112   convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]*
113     convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"];
114   convert["FT4*SEC/SLUG"]["M4*SEC/KG"] =
115     1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"];
116   // Pressure
117   convert["INHG"]["PSF"] = 70.7180803;
118   convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"];
119   convert["ATM"]["INHG"] = 29.9246899;
120   convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"];
121   convert["PSI"]["INHG"] = 2.03625437;
122   convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"];
123   convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals
124   convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"];
125   convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"];
126   convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"];
127   convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"];
128   convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
129   // Mass flow
130   convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
131
132   // Length
133   convert["M"]["M"] = 1.00;
134   convert["FT"]["FT"] = 1.00;
135   convert["IN"]["IN"] = 1.00;
136   // Area
137   convert["M2"]["M2"] = 1.00;
138   convert["FT2"]["FT2"] = 1.00;
139   // Volume
140   convert["IN3"]["IN3"] = 1.00;
141   convert["CC"]["CC"] = 1.0;
142   convert["M3"]["M3"] = 1.0;
143   convert["FT3"]["FT3"] = 1.0;
144   convert["LTR"]["LTR"] = 1.0;
145   // Mass & Weight
146   convert["KG"]["KG"] = 1.00;
147   convert["LBS"]["LBS"] = 1.00;
148   // Moments of Inertia
149   convert["KG*M2"]["KG*M2"] = 1.00;
150   convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
151   // Angles
152   convert["DEG"]["DEG"] = 1.00;
153   convert["RAD"]["RAD"] = 1.00;
154   // Spring force
155   convert["LBS/FT"]["LBS/FT"] = 1.00;
156   convert["N/M"]["N/M"] = 1.00;
157   // Damping force
158   convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
159   convert["N/M/SEC"]["N/M/SEC"] = 1.00;
160   // Damping force (Square law)
161   convert["LBS/FT/SEC2"]["LBS/FT/SEC2"] = 1.00;
162   convert["N/M/SEC2"]["N/M/SEC2"] = 1.00;
163   // Power
164   convert["HP"]["HP"] = 1.00;
165   convert["WATTS"]["WATTS"] = 1.00;
166   // Force
167   convert["N"]["N"] = 1.00;
168   // Velocity
169   convert["FT/SEC"]["FT/SEC"] = 1.00;
170   convert["KTS"]["KTS"] = 1.00;
171   convert["M/S"]["M/S"] = 1.0;
172   // Torque
173   convert["FT*LBS"]["FT*LBS"] = 1.00;
174   convert["N*M"]["N*M"] = 1.00;
175   // Valve
176   convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0;
177   convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0;
178   // Pressure
179   convert["PSI"]["PSI"] = 1.00;
180   convert["PSF"]["PSF"] = 1.00;
181   convert["INHG"]["INHG"] = 1.00;
182   convert["ATM"]["ATM"] = 1.0;
183   convert["PA"]["PA"] = 1.0;
184   convert["N/M2"]["N/M2"] = 1.00;
185   convert["LBS/FT2"]["LBS/FT2"] = 1.00;
186   // Mass flow
187   convert["LBS/SEC"]["LBS/SEC"] = 1.00;
188   convert["KG/MIN"]["KG/MIN"] = 1.0;
189   convert["LBS/MIN"]["LBS/MIN"] = 1.0;
190 }
191
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193
194 Element::~Element(void)
195 {
196   for (unsigned int i=0; i<children.size(); i++) delete children[i];
197   data_lines.clear();
198   attributes.clear();
199   attribute_key.clear();
200 }
201
202 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203
204 string Element::GetAttributeValue(string attr)
205 {
206   int select=-1;
207   for (unsigned int i=0; i<attribute_key.size(); i++) {
208     if (attribute_key[i] == attr) select = i;
209   }
210   if (select < 0) return string("");
211   else return attributes[attr];
212 }
213
214 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215
216 double Element::GetAttributeValueAsNumber(string attr)
217 {
218   string attribute = GetAttributeValue(attr);
219
220   if (attribute.empty()) return HUGE_VAL;
221   else return (atof(attribute.c_str()));
222 }
223
224 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225
226 Element* Element::GetElement(unsigned int el)
227 {
228   if (children.size() > el) {
229     element_index = el;
230     return children[el];
231   }
232   else {
233     element_index = 0;
234     return 0L;
235   }
236 }
237
238 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239
240 Element* Element::GetNextElement(void)
241 {
242   if (children.size() > element_index+1) {
243     element_index++;
244     return children[element_index];
245   } else {
246     element_index = 0;
247     return 0L;
248   }
249 }
250
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
253 string Element::GetDataLine(unsigned int i)
254 {
255   if (data_lines.size() > 0) return data_lines[i];
256   else return string("");
257 }
258
259 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260
261 double Element::GetDataAsNumber(void)
262 {
263   if (data_lines.size() == 1) {
264     return atof(data_lines[0].c_str());
265   } else if (data_lines.size() == 0) {
266     return HUGE_VAL;
267   } else {
268     cerr << "Attempting to get single data value from multiple lines in element " << name << endl;
269     return HUGE_VAL;
270   }
271 }
272
273 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274
275 unsigned int Element::GetNumElements(string element_name)
276 {
277   unsigned int number_of_elements=0;
278   Element* el=FindElement(element_name);
279   while (el) {
280     number_of_elements++;
281     el=FindNextElement(element_name);
282   }
283   return number_of_elements;
284 }
285
286 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287
288 Element* Element::FindElement(string el)
289 {
290   if (el.empty() && children.size() >= 1) {
291     element_index = 1;
292     return children[0];
293   }
294   for (unsigned int i=0; i<children.size(); i++) {
295     if (el == children[i]->GetName()) {
296       element_index = i+1;
297       return children[i];
298     }
299   }
300   element_index = 0;
301   return 0L;
302 }
303
304 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305
306 Element* Element::FindNextElement(string el)
307 {
308   if (el.empty()) {
309     if (element_index < children.size()) {
310       return children[element_index++];
311     } else {
312       element_index = 0;
313       return 0L;
314     }
315   }
316   for (unsigned int i=element_index; i<children.size(); i++) {
317     if (el == children[i]->GetName()) {
318       element_index = i+1;
319       return children[i];
320     }
321   }
322   element_index = 0;
323   return 0L;
324 }
325
326 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327
328 double Element::FindElementValueAsNumber(string el)
329 {
330   Element* element = FindElement(el);
331   if (element) {
332     return element->GetDataAsNumber();
333   } else {
334     cerr << "Attempting to get single data value from multiple lines" << endl;
335     return 0;
336   }
337 }
338
339 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340
341 string Element::FindElementValue(string el)
342 {
343   Element* element = FindElement(el);
344   if (element) {
345     return element->GetDataLine();
346   } else {
347     return "";
348   }
349 }
350
351 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
352
353 double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
354 {
355   Element* element = FindElement(el);
356
357   if (!element) {
358     cerr << "Attempting to get non-existent element " << el << endl;
359     exit(0);
360   }
361
362   string supplied_units = element->GetAttributeValue("unit");
363
364   if (!supplied_units.empty()) {
365     if (convert.find(supplied_units) == convert.end()) {
366       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
367            << " conversion in FGXMLElement.cpp." << endl;
368       exit(-1);
369     }
370     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
371       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
372                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
373       exit(-1);
374     }
375   }
376
377   double value = element->GetDataAsNumber();
378   if (!supplied_units.empty()) {
379     value *= convert[supplied_units][target_units];
380   }
381
382   return value;
383 }
384
385 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386
387 double Element::FindElementValueAsNumberConvertFromTo( string el,
388                                                        string supplied_units,
389                                                        string target_units)
390 {
391   Element* element = FindElement(el);
392   
393   if (!element) {
394     cerr << "Attempting to get non-existent element " << el << endl;
395     exit(0);
396   }
397   
398   if (!supplied_units.empty()) {
399     if (convert.find(supplied_units) == convert.end()) {
400       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
401            << " conversion in FGXMLElement.cpp." << endl;
402       exit(-1);
403     }
404     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
405       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
406                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
407       exit(-1);
408     }
409   }
410
411   double value = element->GetDataAsNumber();
412   if (!supplied_units.empty()) {
413     value *= convert[supplied_units][target_units];
414   }
415
416   return value;
417 }
418
419 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420
421 FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
422 {
423   FGColumnVector3 triplet;
424   Element* item;
425   double value=0.0;
426   string supplied_units = GetAttributeValue("unit");
427
428   if (!supplied_units.empty()) {
429     if (convert.find(supplied_units) == convert.end()) {
430       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
431            << " conversion in FGXMLElement.cpp." << endl;
432       exit(-1);
433     }
434     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
435       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
436                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
437       exit(-1);
438     }
439   }
440
441   item = FindElement("x");
442   if (!item) item = FindElement("roll");
443   if (item) {
444     value = item->GetDataAsNumber();
445     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
446   } else {
447     value = 0.0;
448     cerr << "Could not find an X triplet item for this column vector." << endl;
449   }
450   triplet(1) = value;
451
452   item = FindElement("y");
453   if (!item) item = FindElement("pitch");
454   if (item) {
455     value = item->GetDataAsNumber();
456     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
457   } else {
458     value = 0.0;
459     cerr << "Could not find a Y triplet item for this column vector." << endl;
460   }
461   triplet(2) = value;
462
463   item = FindElement("z");
464   if (!item) item = FindElement("yaw");
465   if (item) {
466     value = item->GetDataAsNumber();
467     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
468   } else {
469     value = 0.0;
470     cerr << "Could not find a Z triplet item for this column vector." << endl;
471   }
472   triplet(3) = value;
473
474   return triplet;
475 }
476
477 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478
479 void Element::Print(unsigned int level)
480 {
481   unsigned int i, spaces;
482
483   level+=2;
484   for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
485   cout << "Element Name: " << name;
486   for (i=0; i<attributes.size(); i++) {
487     cout << "  " << attribute_key[i] << " = " << attributes[attribute_key[i]];
488   }
489   cout << endl;
490   for (i=0; i<data_lines.size(); i++) {
491     for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
492     cout << data_lines[i] << endl;
493   }
494   for (i=0; i<children.size(); i++) {
495     children[i]->Print(level);
496   }
497 }
498
499 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500
501 void Element::AddAttribute(string name, string value)
502 {
503   attribute_key.push_back(name);
504   attributes[name] = value;
505 }
506
507 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508
509 void Element::AddData(string d)
510 {
511   unsigned int string_start = (unsigned int)d.find_first_not_of(" \t");
512   if (string_start > 0) {
513     d.erase(0,string_start);
514   }
515   data_lines.push_back(d);
516 }
517
518 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519
520 } // end namespace JSBSim