![]() |
JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++
|
00001 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00002 00003 Author: Jon Berndt 00004 Date started: 09/28/2004 00005 Purpose: XML element class 00006 Called by: FGXMLParse 00007 00008 ------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) ------------- 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00018 details. 00019 00020 You should have received a copy of the GNU Lesser General Public License along with 00021 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00022 Place - Suite 330, Boston, MA 02111-1307, USA. 00023 00024 Further information about the GNU Lesser General Public License can also be found on 00025 the world wide web at http://www.gnu.org. 00026 00027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00028 INCLUDES 00029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 00030 00031 #include <cmath> 00032 #include <cstdlib> 00033 #include <iostream> 00034 00035 #include "FGXMLElement.h" 00036 #include "string_utilities.h" 00037 00038 using namespace std; 00039 00040 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00041 FORWARD DECLARATIONS 00042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 00043 00044 namespace JSBSim { 00045 00046 static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.38 2012/12/13 04:41:06 jberndt Exp $"; 00047 static const char *IdHdr = ID_XMLELEMENT; 00048 00049 bool Element::converterIsInitialized = false; 00050 map <string, map <string, double> > Element::convert; 00051 00052 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00053 CLASS IMPLEMENTATION 00054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 00055 00056 Element::Element(const string& nm) 00057 { 00058 name = nm; 00059 parent = 0L; 00060 element_index = 0; 00061 00062 if (!converterIsInitialized) { 00063 converterIsInitialized = true; 00064 // convert ["from"]["to"] = factor, so: from * factor = to 00065 // Length 00066 convert["M"]["FT"] = 3.2808399; 00067 convert["FT"]["M"] = 1.0/convert["M"]["FT"]; 00068 convert["CM"]["FT"] = 0.032808399; 00069 convert["FT"]["CM"] = 1.0/convert["CM"]["FT"]; 00070 convert["KM"]["FT"] = 3280.8399; 00071 convert["FT"]["KM"] = 1.0/convert["KM"]["FT"]; 00072 convert["FT"]["IN"] = 12.0; 00073 convert["IN"]["FT"] = 1.0/convert["FT"]["IN"]; 00074 convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"]; 00075 convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"]; 00076 // Area 00077 convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"]; 00078 convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"]; 00079 convert["CM2"]["FT2"] = convert["CM"]["FT"]*convert["CM"]["FT"]; 00080 convert["FT2"]["CM2"] = 1.0/convert["CM2"]["FT2"]; 00081 convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"]; 00082 convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"]; 00083 convert["FT2"]["IN2"] = 144.0; 00084 convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"]; 00085 // Volume 00086 convert["IN3"]["CC"] = 16.387064; 00087 convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"]; 00088 convert["FT3"]["IN3"] = 1728.0; 00089 convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"]; 00090 convert["M3"]["FT3"] = 35.3146667; 00091 convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"]; 00092 convert["LTR"]["IN3"] = 61.0237441; 00093 convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"]; 00094 // Mass & Weight 00095 convert["LBS"]["KG"] = 0.45359237; 00096 convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"]; 00097 convert["SLUG"]["KG"] = 14.59390; 00098 convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"]; 00099 // Moments of Inertia 00100 convert["SLUG*FT2"]["KG*M2"] = 1.35594; 00101 convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"]; 00102 // Angles 00103 convert["RAD"]["DEG"] = 180.0/M_PI; 00104 convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"]; 00105 // Angular rates 00106 convert["RAD/SEC"]["DEG/SEC"] = convert["RAD"]["DEG"]; 00107 convert["DEG/SEC"]["RAD/SEC"] = 1.0/convert["RAD/SEC"]["DEG/SEC"]; 00108 // Spring force 00109 convert["LBS/FT"]["N/M"] = 14.5939; 00110 convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"]; 00111 // Damping force 00112 convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939; 00113 convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"]; 00114 // Damping force (Square Law) 00115 convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259; 00116 convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"]; 00117 // Power 00118 convert["WATTS"]["HP"] = 0.001341022; 00119 convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"]; 00120 // Force 00121 convert["N"]["LBS"] = 0.22482; 00122 convert["LBS"]["N"] = 1.0/convert["N"]["LBS"]; 00123 // Velocity 00124 convert["KTS"]["FT/SEC"] = 1.68781; 00125 convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"]; 00126 convert["M/S"]["FT/S"] = 3.2808399; 00127 convert["M/SEC"]["FT/SEC"] = 3.2808399; 00128 convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"]; 00129 convert["M/SEC"]["FT/SEC"] = 3.2808399; 00130 convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"]; 00131 convert["KM/SEC"]["FT/SEC"] = 3280.8399; 00132 convert["FT/SEC"]["KM/SEC"] = 1.0/convert["KM/SEC"]["FT/SEC"]; 00133 // Torque 00134 convert["FT*LBS"]["N*M"] = 1.35581795; 00135 convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"]; 00136 // Valve 00137 convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]* 00138 convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"]; 00139 convert["FT4*SEC/SLUG"]["M4*SEC/KG"] = 00140 1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"]; 00141 // Pressure 00142 convert["INHG"]["PSF"] = 70.7180803; 00143 convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"]; 00144 convert["ATM"]["INHG"] = 29.9246899; 00145 convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"]; 00146 convert["PSI"]["INHG"] = 2.03625437; 00147 convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"]; 00148 convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals 00149 convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"]; 00150 convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"]; 00151 convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"]; 00152 convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"]; 00153 convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"]; 00154 // Mass flow 00155 convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"]; 00156 // Fuel Consumption 00157 convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083; 00158 convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"]; 00159 // Density 00160 convert["KG/L"]["LBS/GAL"] = 8.3454045; 00161 convert["LBS/GAL"]["KG/L"] = 1.0/convert["KG/L"]["LBS/GAL"]; 00162 00163 // Length 00164 convert["M"]["M"] = 1.00; 00165 convert["KM"]["KM"] = 1.00; 00166 convert["FT"]["FT"] = 1.00; 00167 convert["IN"]["IN"] = 1.00; 00168 // Area 00169 convert["M2"]["M2"] = 1.00; 00170 convert["FT2"]["FT2"] = 1.00; 00171 // Volume 00172 convert["IN3"]["IN3"] = 1.00; 00173 convert["CC"]["CC"] = 1.0; 00174 convert["M3"]["M3"] = 1.0; 00175 convert["FT3"]["FT3"] = 1.0; 00176 convert["LTR"]["LTR"] = 1.0; 00177 // Mass & Weight 00178 convert["KG"]["KG"] = 1.00; 00179 convert["LBS"]["LBS"] = 1.00; 00180 // Moments of Inertia 00181 convert["KG*M2"]["KG*M2"] = 1.00; 00182 convert["SLUG*FT2"]["SLUG*FT2"] = 1.00; 00183 // Angles 00184 convert["DEG"]["DEG"] = 1.00; 00185 convert["RAD"]["RAD"] = 1.00; 00186 // Angular rates 00187 convert["DEG/SEC"]["DEG/SEC"] = 1.00; 00188 convert["RAD/SEC"]["RAD/SEC"] = 1.00; 00189 // Spring force 00190 convert["LBS/FT"]["LBS/FT"] = 1.00; 00191 convert["N/M"]["N/M"] = 1.00; 00192 // Damping force 00193 convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00; 00194 convert["N/M/SEC"]["N/M/SEC"] = 1.00; 00195 // Damping force (Square law) 00196 convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00; 00197 convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00; 00198 // Power 00199 convert["HP"]["HP"] = 1.00; 00200 convert["WATTS"]["WATTS"] = 1.00; 00201 // Force 00202 convert["N"]["N"] = 1.00; 00203 // Velocity 00204 convert["FT/SEC"]["FT/SEC"] = 1.00; 00205 convert["KTS"]["KTS"] = 1.00; 00206 convert["M/S"]["M/S"] = 1.0; 00207 convert["M/SEC"]["M/SEC"] = 1.0; 00208 convert["KM/SEC"]["KM/SEC"] = 1.0; 00209 // Torque 00210 convert["FT*LBS"]["FT*LBS"] = 1.00; 00211 convert["N*M"]["N*M"] = 1.00; 00212 // Valve 00213 convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0; 00214 convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0; 00215 // Pressure 00216 convert["PSI"]["PSI"] = 1.00; 00217 convert["PSF"]["PSF"] = 1.00; 00218 convert["INHG"]["INHG"] = 1.00; 00219 convert["ATM"]["ATM"] = 1.0; 00220 convert["PA"]["PA"] = 1.0; 00221 convert["N/M2"]["N/M2"] = 1.00; 00222 convert["LBS/FT2"]["LBS/FT2"] = 1.00; 00223 // Mass flow 00224 convert["LBS/SEC"]["LBS/SEC"] = 1.00; 00225 convert["KG/MIN"]["KG/MIN"] = 1.0; 00226 convert["LBS/MIN"]["LBS/MIN"] = 1.0; 00227 // Fuel Consumption 00228 convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0; 00229 convert["KG/KW*HR"]["KG/KW*HR"] = 1.0; 00230 // Density 00231 convert["KG/L"]["KG/L"] = 1.0; 00232 convert["LBS/GAL"]["LBS/GAL"] = 1.0; 00233 } 00234 attribute_key.resize(0); 00235 } 00236 00237 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00238 00239 Element::~Element(void) 00240 { 00241 for (unsigned int i=0; i<children.size(); i++) delete children[i]; 00242 data_lines.clear(); 00243 attributes.clear(); 00244 attribute_key.clear(); 00245 } 00246 00247 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00248 00249 string Element::GetAttributeValue(const string& attr) 00250 { 00251 if (HasAttribute(attr)) return attributes[attr]; 00252 else return (""); 00253 } 00254 00255 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00256 00257 bool Element::HasAttribute(const string& attr) 00258 { 00259 bool status=true; 00260 int select=-1; 00261 00262 unsigned int attr_cnt = attribute_key.size(); 00263 00264 for (unsigned int i=0; i<attr_cnt; i++) { 00265 if (attribute_key[i] == attr) select = i; 00266 } 00267 if (select < 0) status=false; 00268 return status; 00269 } 00270 00271 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00272 00273 double Element::GetAttributeValueAsNumber(const string& attr) 00274 { 00275 string attribute = GetAttributeValue(attr); 00276 00277 if (attribute.empty()) return HUGE_VAL; 00278 else { 00279 double number=0; 00280 if (is_number(trim(attribute))) 00281 number = atof(attribute.c_str()); 00282 else 00283 throw("Expecting numeric attribute value, but got: " + attribute); 00284 00285 return (number); 00286 } 00287 } 00288 00289 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00290 00291 Element* Element::GetElement(unsigned int el) 00292 { 00293 if (children.size() > el) { 00294 element_index = el; 00295 return children[el]; 00296 } 00297 else { 00298 element_index = 0; 00299 return 0L; 00300 } 00301 } 00302 00303 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00304 00305 Element* Element::GetNextElement(void) 00306 { 00307 if (children.size() > element_index+1) { 00308 element_index++; 00309 return children[element_index]; 00310 } else { 00311 element_index = 0; 00312 return 0L; 00313 } 00314 } 00315 00316 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00317 00318 string Element::GetDataLine(unsigned int i) 00319 { 00320 if (data_lines.size() > 0) return data_lines[i]; 00321 else return string(""); 00322 } 00323 00324 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00325 00326 double Element::GetDataAsNumber(void) 00327 { 00328 if (data_lines.size() == 1) { 00329 double number=0; 00330 if (is_number(trim(data_lines[0]))) 00331 number = atof(data_lines[0].c_str()); 00332 else 00333 throw("Expected numeric value, but got: " + data_lines[0]); 00334 00335 return number; 00336 } else if (data_lines.size() == 0) { 00337 return HUGE_VAL; 00338 } else { 00339 cerr << "Attempting to get single data value from multiple lines in element " << name << endl; 00340 return HUGE_VAL; 00341 } 00342 } 00343 00344 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00345 00346 unsigned int Element::GetNumElements(const string& element_name) 00347 { 00348 unsigned int number_of_elements=0; 00349 Element* el=FindElement(element_name); 00350 while (el) { 00351 number_of_elements++; 00352 el=FindNextElement(element_name); 00353 } 00354 return number_of_elements; 00355 } 00356 00357 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00358 00359 Element* Element::FindElement(const string& el) 00360 { 00361 if (el.empty() && children.size() >= 1) { 00362 element_index = 1; 00363 return children[0]; 00364 } 00365 for (unsigned int i=0; i<children.size(); i++) { 00366 if (el == children[i]->GetName()) { 00367 element_index = i+1; 00368 return children[i]; 00369 } 00370 } 00371 element_index = 0; 00372 return 0L; 00373 } 00374 00375 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00376 00377 Element* Element::FindNextElement(const string& el) 00378 { 00379 if (el.empty()) { 00380 if (element_index < children.size()) { 00381 return children[element_index++]; 00382 } else { 00383 element_index = 0; 00384 return 0L; 00385 } 00386 } 00387 for (unsigned int i=element_index; i<children.size(); i++) { 00388 if (el == children[i]->GetName()) { 00389 element_index = i+1; 00390 return children[i]; 00391 } 00392 } 00393 element_index = 0; 00394 return 0L; 00395 } 00396 00397 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00398 00399 double Element::FindElementValueAsNumber(const string& el) 00400 { 00401 Element* element = FindElement(el); 00402 if (element) { 00403 double value = element->GetDataAsNumber(); 00404 value = DisperseValue(element, value); 00405 return value; 00406 } else { 00407 cerr << "Attempting to get single data value from multiple lines" << endl; 00408 return 0; 00409 } 00410 } 00411 00412 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00413 00414 string Element::FindElementValue(const string& el) 00415 { 00416 Element* element = FindElement(el); 00417 if (element) { 00418 return element->GetDataLine(); 00419 } else { 00420 return ""; 00421 } 00422 } 00423 00424 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00425 00426 double Element::FindElementValueAsNumberConvertTo(const string& el, const string& target_units) 00427 { 00428 Element* element = FindElement(el); 00429 00430 if (!element) { 00431 cerr << "Attempting to get non-existent element " << el << endl; 00432 exit(0); 00433 } 00434 00435 string supplied_units = element->GetAttributeValue("unit"); 00436 00437 if (!supplied_units.empty()) { 00438 if (convert.find(supplied_units) == convert.end()) { 00439 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" 00440 << " conversion in FGXMLElement.cpp." << endl; 00441 exit(-1); 00442 } 00443 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { 00444 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " 00445 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; 00446 exit(-1); 00447 } 00448 } 00449 00450 double value = element->GetDataAsNumber(); 00451 if (!supplied_units.empty()) { 00452 value *= convert[supplied_units][target_units]; 00453 } 00454 00455 value = DisperseValue(element, value, supplied_units, target_units); 00456 00457 return value; 00458 } 00459 00460 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00461 00462 double Element::FindElementValueAsNumberConvertFromTo( const string& el, 00463 const string& supplied_units, 00464 const string& target_units) 00465 { 00466 Element* element = FindElement(el); 00467 00468 if (!element) { 00469 cerr << "Attempting to get non-existent element " << el << endl; 00470 exit(0); 00471 } 00472 00473 if (!supplied_units.empty()) { 00474 if (convert.find(supplied_units) == convert.end()) { 00475 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" 00476 << " conversion in FGXMLElement.cpp." << endl; 00477 exit(-1); 00478 } 00479 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { 00480 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " 00481 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; 00482 exit(-1); 00483 } 00484 } 00485 00486 double value = element->GetDataAsNumber(); 00487 if (!supplied_units.empty()) { 00488 value *= convert[supplied_units][target_units]; 00489 } 00490 00491 value = DisperseValue(element, value, supplied_units, target_units); 00492 00493 return value; 00494 } 00495 00496 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00497 00498 FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units) 00499 { 00500 FGColumnVector3 triplet; 00501 Element* item; 00502 double value=0.0; 00503 string supplied_units = GetAttributeValue("unit"); 00504 00505 if (!supplied_units.empty()) { 00506 if (convert.find(supplied_units) == convert.end()) { 00507 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit" 00508 << " conversion in FGXMLElement.cpp." << endl; 00509 exit(-1); 00510 } 00511 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { 00512 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " 00513 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl; 00514 exit(-1); 00515 } 00516 } 00517 00518 item = FindElement("x"); 00519 if (!item) item = FindElement("roll"); 00520 if (item) { 00521 value = item->GetDataAsNumber(); 00522 if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; 00523 triplet(1) = DisperseValue(item, value, supplied_units, target_units); 00524 } else { 00525 triplet(1) = 0.0; 00526 } 00527 00528 00529 item = FindElement("y"); 00530 if (!item) item = FindElement("pitch"); 00531 if (item) { 00532 value = item->GetDataAsNumber(); 00533 if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; 00534 triplet(2) = DisperseValue(item, value, supplied_units, target_units); 00535 } else { 00536 triplet(2) = 0.0; 00537 } 00538 00539 item = FindElement("z"); 00540 if (!item) item = FindElement("yaw"); 00541 if (item) { 00542 value = item->GetDataAsNumber(); 00543 if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; 00544 triplet(3) = DisperseValue(item, value, supplied_units, target_units); 00545 } else { 00546 triplet(3) = 0.0; 00547 } 00548 00549 return triplet; 00550 } 00551 00552 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00553 00554 double Element::DisperseValue(Element *e, double val, const std::string supplied_units, const std::string target_units) 00555 { 00556 double value=val; 00557 double disp=0.0; 00558 if (e->HasAttribute("dispersion")) { 00559 disp = e->GetAttributeValueAsNumber("dispersion"); 00560 if (!supplied_units.empty()) disp *= convert[supplied_units][target_units]; 00561 string attType = e->GetAttributeValue("type"); 00562 if (attType == "gaussian") { 00563 value = val + disp*GaussianRandomNumber(); 00564 } else if (attType == "uniform") { 00565 value = val + disp * ((((double)rand()/RAND_MAX)-0.5)*2.0); 00566 } else { 00567 std::cerr << "Unknown dispersion type" << endl; 00568 throw("Unknown dispersion type"); 00569 } 00570 00571 } 00572 return value; 00573 } 00574 00575 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00576 00577 double Element::GaussianRandomNumber(void) 00578 { 00579 static double V1, V2, S; 00580 static int phase = 0; 00581 double X; 00582 00583 if (phase == 0) { 00584 V1 = V2 = S = X = 0.0; 00585 00586 do { 00587 double U1 = (double)rand() / RAND_MAX; 00588 double U2 = (double)rand() / RAND_MAX; 00589 00590 V1 = 2 * U1 - 1; 00591 V2 = 2 * U2 - 1; 00592 S = V1 * V1 + V2 * V2; 00593 } while(S >= 1 || S == 0); 00594 00595 X = V1 * sqrt(-2 * log(S) / S); 00596 } else 00597 X = V2 * sqrt(-2 * log(S) / S); 00598 00599 phase = 1 - phase; 00600 00601 return X; 00602 } 00603 00604 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00605 00606 void Element::Print(unsigned int level) 00607 { 00608 unsigned int i, spaces; 00609 00610 level+=2; 00611 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output 00612 cout << "Element Name: " << name; 00613 for (i=0; i<attributes.size(); i++) { 00614 cout << " " << attribute_key[i] << " = " << attributes[attribute_key[i]]; 00615 } 00616 cout << endl; 00617 for (i=0; i<data_lines.size(); i++) { 00618 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output 00619 cout << data_lines[i] << endl; 00620 } 00621 for (i=0; i<children.size(); i++) { 00622 children[i]->Print(level); 00623 } 00624 } 00625 00626 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00627 00628 void Element::AddAttribute(const string& name, const string& value) 00629 { 00630 attribute_key.push_back(name); 00631 attributes[name] = value; 00632 } 00633 00634 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00635 00636 void Element::AddData(string d) 00637 { 00638 string::size_type string_start = d.find_first_not_of(" \t"); 00639 if (string_start != string::npos && string_start > 0) { 00640 d.erase(0,string_start); 00641 } 00642 data_lines.push_back(d); 00643 } 00644 00645 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00646 00647 } // end namespace JSBSim