![]() |
JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++
|
00001 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00002 00003 Module: FGFCSComponent.cpp 00004 Author: Jon S. Berndt 00005 Date started: 11/1999 00006 00007 ------------- Copyright (C) 2000 ------------- 00008 00009 This program is free software; you can redistribute it and/or modify it under 00010 the terms of the GNU Lesser General Public License as published by the Free Software 00011 Foundation; either version 2 of the License, or (at your option) any later 00012 version. 00013 00014 This program is distributed in the hope that it will be useful, but WITHOUT 00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00016 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00017 details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA. 00022 00023 Further information about the GNU Lesser General Public License can also be found on 00024 the world wide web at http://www.gnu.org. 00025 00026 FUNCTIONAL DESCRIPTION 00027 -------------------------------------------------------------------------------- 00028 00029 HISTORY 00030 -------------------------------------------------------------------------------- 00031 00032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00033 COMMENTS, REFERENCES, and NOTES 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 00036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00037 INCLUDES 00038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 00039 00040 #include "FGFCSComponent.h" 00041 #include "input_output/FGPropertyManager.h" 00042 #include "input_output/FGXMLElement.h" 00043 #include "math/FGPropertyValue.h" 00044 #include <iostream> 00045 #include <cstdlib> 00046 00047 using namespace std; 00048 00049 namespace JSBSim { 00050 00051 static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.35 2013/01/26 17:06:50 bcoconni Exp $"; 00052 static const char *IdHdr = ID_FCSCOMPONENT; 00053 00054 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00055 CLASS IMPLEMENTATION 00056 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 00057 00058 FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs) 00059 { 00060 Element *input_element, *clip_el; 00061 Input = Output = clipmin = clipmax = delay_time = 0.0; 00062 treenode = 0; 00063 delay = index = 0; 00064 ClipMinPropertyNode = ClipMaxPropertyNode = 0; 00065 clipMinSign = clipMaxSign = 1.0; 00066 IsOutput = clip = false; 00067 string input, clip_string; 00068 dt = fcs->GetDt(); 00069 00070 PropertyManager = fcs->GetPropertyManager(); 00071 if (element->GetName() == string("lag_filter")) { 00072 Type = "LAG_FILTER"; 00073 } else if (element->GetName() == string("lead_lag_filter")) { 00074 Type = "LEAD_LAG_FILTER"; 00075 } else if (element->GetName() == string("washout_filter")) { 00076 Type = "WASHOUT_FILTER"; 00077 } else if (element->GetName() == string("second_order_filter")) { 00078 Type = "SECOND_ORDER_FILTER"; 00079 } else if (element->GetName() == string("integrator")) { 00080 Type = "INTEGRATOR"; 00081 } else if (element->GetName() == string("summer")) { 00082 Type = "SUMMER"; 00083 } else if (element->GetName() == string("pure_gain")) { 00084 Type = "PURE_GAIN"; 00085 } else if (element->GetName() == string("scheduled_gain")) { 00086 Type = "SCHEDULED_GAIN"; 00087 } else if (element->GetName() == string("aerosurface_scale")) { 00088 Type = "AEROSURFACE_SCALE"; 00089 } else if (element->GetName() == string("switch")) { 00090 Type = "SWITCH"; 00091 } else if (element->GetName() == string("kinematic")) { 00092 Type = "KINEMATIC"; 00093 } else if (element->GetName() == string("deadband")) { 00094 Type = "DEADBAND"; 00095 } else if (element->GetName() == string("fcs_function")) { 00096 Type = "FCS_FUNCTION"; 00097 } else if (element->GetName() == string("pid")) { 00098 Type = "PID"; 00099 } else if (element->GetName() == string("sensor")) { 00100 Type = "SENSOR"; 00101 } else if (element->GetName() == string("accelerometer")) { 00102 Type = "ACCELEROMETER"; 00103 } else if (element->GetName() == string("magnetometer")) { 00104 Type = "MAGNETOMETER"; 00105 } else if (element->GetName() == string("gyro")) { 00106 Type = "GYRO"; 00107 } else if (element->GetName() == string("actuator")) { 00108 Type = "ACTUATOR"; 00109 } else { // illegal component in this channel 00110 Type = "UNKNOWN"; 00111 } 00112 00113 Name = element->GetAttributeValue("name"); 00114 00115 input_element = element->FindElement("input"); 00116 while (input_element) { 00117 input = input_element->GetDataLine(); 00118 if (input[0] == '-') { 00119 InputSigns.push_back(-1.0); 00120 input.erase(0,1); 00121 } else { 00122 InputSigns.push_back( 1.0); 00123 } 00124 FGPropertyNode* node = 0L; 00125 if (PropertyManager->HasNode(input)) { 00126 node = PropertyManager->GetNode(input); 00127 InputNodes.push_back(new FGPropertyValue( node )); 00128 } else { 00129 InputNodes.push_back(new FGPropertyValue( input, 00130 PropertyManager )); 00131 } 00132 InputNames.push_back( input ); 00133 00134 input_element = element->FindNextElement("input"); 00135 } 00136 00137 Element *out_elem = element->FindElement("output"); 00138 while (out_elem) { 00139 IsOutput = true; 00140 string output_node_name = out_elem->GetDataLine(); 00141 FGPropertyNode* OutputNode = PropertyManager->GetNode( output_node_name, true ); 00142 OutputNodes.push_back(OutputNode); 00143 if (!OutputNode) { 00144 cerr << endl << " Unable to process property: " << output_node_name << endl; 00145 throw(string("Invalid output property name in flight control definition")); 00146 } 00147 out_elem = element->FindNextElement("output"); 00148 } 00149 00150 Element* delay_elem = element->FindElement("delay"); 00151 if ( delay_elem ) { 00152 delay_time = delay_elem->GetDataAsNumber(); 00153 string delayType = delay_elem->GetAttributeValue("type"); 00154 if (delayType.length() > 0) { 00155 if (delayType == "time") { 00156 delay = (unsigned int)(delay_time / dt); 00157 } else if (delayType == "frames") { 00158 delay = (unsigned int)delay_time; 00159 } else { 00160 cerr << "Unallowed delay type" << endl; 00161 } 00162 } else { 00163 delay = (unsigned int)(delay_time / dt); 00164 } 00165 output_array.resize(delay); 00166 for (unsigned int i=0; i<delay; i++) output_array[i] = 0.0; 00167 } 00168 00169 clip_el = element->FindElement("clipto"); 00170 if (clip_el) { 00171 clip_string = clip_el->FindElementValue("min"); 00172 if (!is_number(clip_string)) { // it's a property 00173 if (clip_string[0] == '-') { 00174 clipMinSign = -1.0; 00175 clip_string.erase(0,1); 00176 } 00177 ClipMinPropertyNode = PropertyManager->GetNode( clip_string ); 00178 } else { 00179 clipmin = clip_el->FindElementValueAsNumber("min"); 00180 } 00181 clip_string = clip_el->FindElementValue("max"); 00182 if (!is_number(clip_string)) { // it's a property 00183 if (clip_string[0] == '-') { 00184 clipMaxSign = -1.0; 00185 clip_string.erase(0,1); 00186 } 00187 ClipMaxPropertyNode = PropertyManager->GetNode( clip_string ); 00188 } else { 00189 clipmax = clip_el->FindElementValueAsNumber("max"); 00190 } 00191 clip = true; 00192 } 00193 00194 Debug(0); 00195 } 00196 00197 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00198 00199 FGFCSComponent::~FGFCSComponent() 00200 { 00201 Debug(1); 00202 for (unsigned int i=0; i<InputNodes.size(); i++) { 00203 delete InputNodes[i]; 00204 } 00205 } 00206 00207 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00208 00209 void FGFCSComponent::SetOutput(void) 00210 { 00211 for (unsigned int i=0; i<OutputNodes.size(); i++) OutputNodes[i]->setDoubleValue(Output); 00212 } 00213 00214 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00215 00216 bool FGFCSComponent::Run(void) 00217 { 00218 return true; 00219 } 00220 00221 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00222 00223 void FGFCSComponent::Delay(void) 00224 { 00225 output_array[index] = Output; 00226 if ((unsigned int)index == delay-1) index = 0; 00227 else index++; 00228 Output = output_array[index]; 00229 } 00230 00231 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00232 00233 void FGFCSComponent::Clip(void) 00234 { 00235 if (clip) { 00236 if (ClipMinPropertyNode != 0) clipmin = clipMinSign*ClipMinPropertyNode->getDoubleValue(); 00237 if (ClipMaxPropertyNode != 0) clipmax = clipMaxSign*ClipMaxPropertyNode->getDoubleValue(); 00238 if (Output > clipmax) Output = clipmax; 00239 else if (Output < clipmin) Output = clipmin; 00240 } 00241 } 00242 00243 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00244 // 00245 // The old way of naming FCS components allowed upper or lower case, spaces, etc. 00246 // but then the names were modified to fit into a property name heirarchy. This 00247 // was confusing (it wasn't done intentionally - it was a carryover from the early 00248 // design). We now support the direct naming of properties in the FCS component 00249 // name attribute. The old way is supported in code at this time, but deprecated. 00250 00251 void FGFCSComponent::bind(void) 00252 { 00253 string tmp; 00254 if (Name.find("/") == string::npos) { 00255 tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true); 00256 } else { 00257 tmp = Name; 00258 } 00259 PropertyManager->Tie( tmp, this, &FGFCSComponent::GetOutput); 00260 } 00261 00262 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00263 // The bitmasked value choices are as follows: 00264 // unset: In this case (the default) JSBSim would only print 00265 // out the normally expected messages, essentially echoing 00266 // the config files as they are read. If the environment 00267 // variable is not set, debug_lvl is set to 1 internally 00268 // 0: This requests JSBSim not to output any messages 00269 // whatsoever. 00270 // 1: This value explicity requests the normal JSBSim 00271 // startup messages 00272 // 2: This value asks for a message to be printed out when 00273 // a class is instantiated 00274 // 4: When this value is set, a message is displayed when a 00275 // FGModel object executes its Run() method 00276 // 8: When this value is set, various runtime state variables 00277 // are printed out periodically 00278 // 16: When set various parameters are sanity checked and 00279 // a message is printed out when they go out of bounds 00280 00281 void FGFCSComponent::Debug(int from) 00282 { 00283 string propsign=""; 00284 00285 if (debug_lvl <= 0) return; 00286 00287 if (debug_lvl & 1) { // Standard console startup message output 00288 if (from == 0) { 00289 cout << endl << " Loading Component \"" << Name 00290 << "\" of type: " << Type << endl; 00291 00292 if (clip) { 00293 if (ClipMinPropertyNode != 0L) { 00294 if (clipMinSign < 0.0) propsign="-"; 00295 cout << " Minimum limit: " << propsign << ClipMinPropertyNode->GetName() << endl; 00296 propsign=""; 00297 } else { 00298 cout << " Minimum limit: " << clipmin << endl; 00299 } 00300 if (ClipMaxPropertyNode != 0L) { 00301 if (clipMaxSign < 0.0) propsign="-"; 00302 cout << " Maximum limit: " << propsign << ClipMaxPropertyNode->GetName() << endl; 00303 propsign=""; 00304 } else { 00305 cout << " Maximum limit: " << clipmax << endl; 00306 } 00307 } 00308 if (delay > 0) cout <<" Frame delay: " << delay 00309 << " frames (" << delay*dt << " sec)" << endl; 00310 } 00311 } 00312 if (debug_lvl & 2 ) { // Instantiation/Destruction notification 00313 if (from == 0) cout << "Instantiated: FGFCSComponent" << endl; 00314 if (from == 1) cout << "Destroyed: FGFCSComponent" << endl; 00315 } 00316 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects 00317 } 00318 if (debug_lvl & 8 ) { // Runtime state variables 00319 } 00320 if (debug_lvl & 16) { // Sanity checking 00321 } 00322 if (debug_lvl & 64) { 00323 if (from == 0) { // Constructor 00324 cout << IdSrc << endl; 00325 cout << IdHdr << endl; 00326 } 00327 } 00328 } 00329 }