JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++

FGGain.cpp

00001 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00002 
00003  Module:       FGGain.cpp
00004  Author:       Jon S. Berndt
00005  Date started: 4/2000
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 "FGGain.h"
00041 #include "input_output/FGXMLElement.h"
00042 #include <iostream>
00043 #include <string>
00044 #include <cstdlib>
00045 
00046 using namespace std;
00047 
00048 namespace JSBSim {
00049 
00050 static const char *IdSrc = "$Id: FGGain.cpp,v 1.23 2011/04/18 08:51:12 andgi Exp $";
00051 static const char *IdHdr = ID_GAIN;
00052 
00053 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00054 CLASS IMPLEMENTATION
00055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00056 
00057 FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
00058 {
00059   Element *scale_element, *zero_centered;
00060   string strScheduledBy, gain_string, sZeroCentered;
00061 
00062   GainPropertyNode = 0;
00063   GainPropertySign = 1.0;
00064   Gain = 1.000;
00065   Rows = 0;
00066   Table = 0;
00067   InMin = -1.0;
00068   InMax =  1.0;
00069   OutMin = OutMax = 0.0;
00070 
00071   if (Type == "PURE_GAIN") {
00072     if ( !element->FindElement("gain") ) {
00073       cerr << highint << "      No GAIN specified (default: 1.0)" << normint << endl;
00074     }
00075   }
00076 
00077   if ( element->FindElement("gain") ) {
00078     gain_string = element->FindElementValue("gain");
00079     if (!is_number(gain_string)) { // property
00080       if (gain_string[0] == '-') {
00081        GainPropertySign = -1.0;
00082        gain_string.erase(0,1);
00083       }
00084       GainPropertyNode = PropertyManager->GetNode(gain_string);
00085     } else {
00086       Gain = element->FindElementValueAsNumber("gain");
00087     }
00088   }
00089 
00090   if (Type == "AEROSURFACE_SCALE") {
00091     scale_element = element->FindElement("domain");
00092     if (scale_element) {
00093       if (scale_element->FindElement("max") && scale_element->FindElement("min") )
00094       {
00095         InMax = scale_element->FindElementValueAsNumber("max");
00096         InMin = scale_element->FindElementValueAsNumber("min");
00097       }
00098     }
00099     scale_element = element->FindElement("range");
00100     if (!scale_element) throw(string("No range supplied for aerosurface scale component"));
00101     if (scale_element->FindElement("max") && scale_element->FindElement("min") )
00102     {
00103       OutMax = scale_element->FindElementValueAsNumber("max");
00104       OutMin = scale_element->FindElementValueAsNumber("min");
00105     } else {
00106       cerr << "Maximum and minimum output values must be supplied for the "
00107               "aerosurface scale component" << endl;
00108       exit(-1);
00109     }
00110     ZeroCentered = true;
00111     zero_centered = element->FindElement("zero_centered");
00112     //ToDo if zero centered, then mins must be <0 and max's must be >0
00113     if (zero_centered) {
00114       sZeroCentered = element->FindElementValue("zero_centered");
00115       if (sZeroCentered == string("0") || sZeroCentered == string("false")) {
00116         ZeroCentered = false;
00117       }
00118     }
00119   }
00120 
00121   if (Type == "SCHEDULED_GAIN") {
00122     if (element->FindElement("table")) {
00123       Table = new FGTable(PropertyManager, element->FindElement("table"));
00124     } else {
00125       cerr << "A table must be provided for the scheduled gain component" << endl;
00126       exit(-1);
00127     }
00128   }
00129 
00130   FGFCSComponent::bind();
00131 
00132   Debug(0);
00133 }
00134 
00135 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00136 
00137 FGGain::~FGGain()
00138 {
00139   delete Table;
00140 
00141   Debug(1);
00142 }
00143 
00144 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00145 
00146 bool FGGain::Run(void )
00147 {
00148   double SchedGain = 1.0;
00149 
00150   Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
00151 
00152   if (GainPropertyNode != 0) Gain = GainPropertyNode->getDoubleValue() * GainPropertySign;
00153 
00154   if (Type == "PURE_GAIN") {                       // PURE_GAIN
00155 
00156     Output = Gain * Input;
00157 
00158   } else if (Type == "SCHEDULED_GAIN") {           // SCHEDULED_GAIN
00159 
00160     SchedGain = Table->GetValue();
00161     Output = Gain * SchedGain * Input;
00162 
00163   } else if (Type == "AEROSURFACE_SCALE") {        // AEROSURFACE_SCALE
00164 
00165     if (ZeroCentered) {
00166       if (Input == 0.0) {
00167         Output = 0.0;
00168       } else if (Input > 0) {
00169         Output = (Input / InMax) * OutMax;
00170       } else {
00171         Output = (Input / InMin) * OutMin;
00172       }
00173     } else {
00174       Output = OutMin + ((Input - InMin) / (InMax - InMin)) * (OutMax - OutMin);
00175     }
00176 
00177     Output *= Gain;
00178   }
00179 
00180   Clip();
00181   if (IsOutput) SetOutput();
00182 
00183   return true;
00184 }
00185 
00186 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00187 //    The bitmasked value choices are as follows:
00188 //    unset: In this case (the default) JSBSim would only print
00189 //       out the normally expected messages, essentially echoing
00190 //       the config files as they are read. If the environment
00191 //       variable is not set, debug_lvl is set to 1 internally
00192 //    0: This requests JSBSim not to output any messages
00193 //       whatsoever.
00194 //    1: This value explicity requests the normal JSBSim
00195 //       startup messages
00196 //    2: This value asks for a message to be printed out when
00197 //       a class is instantiated
00198 //    4: When this value is set, a message is displayed when a
00199 //       FGModel object executes its Run() method
00200 //    8: When this value is set, various runtime state variables
00201 //       are printed out periodically
00202 //    16: When set various parameters are sanity checked and
00203 //       a message is printed out when they go out of bounds
00204 
00205 void FGGain::Debug(int from)
00206 {
00207   if (debug_lvl <= 0) return;
00208 
00209   if (debug_lvl & 1) { // Standard console startup message output
00210     if (from == 0) { // Constructor
00211       if (InputSigns[0] < 0)
00212         cout << "      INPUT: -" << InputNodes[0]->GetName() << endl;
00213       else
00214         cout << "      INPUT: " << InputNodes[0]->GetName() << endl;
00215 
00216       if (GainPropertyNode != 0) {
00217         cout << "      GAIN: " << GainPropertyNode->GetName() << endl;
00218       } else {
00219         cout << "      GAIN: " << Gain << endl;
00220       }
00221       if (IsOutput) {
00222         for (unsigned int i=0; i<OutputNodes.size(); i++)
00223           cout << "      OUTPUT: " << OutputNodes[i]->getName() << endl;
00224       }
00225       if (Type == "AEROSURFACE_SCALE") {
00226         cout << "      In/Out Mapping:" << endl;
00227         cout << "        Input MIN: " << InMin << endl;
00228         cout << "        Input MAX: " << InMax << endl;
00229         cout << "        Output MIN: " << OutMin << endl;
00230         cout << "        Output MAX: " << OutMax << endl;
00231       }
00232       if (Table != 0) {
00233         cout << "      Scheduled by table: " << endl;
00234         Table->Print();
00235       }
00236     }
00237   }
00238   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
00239     if (from == 0) cout << "Instantiated: FGGain" << endl;
00240     if (from == 1) cout << "Destroyed:    FGGain" << endl;
00241   }
00242   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
00243   }
00244   if (debug_lvl & 8 ) { // Runtime state variables
00245   }
00246   if (debug_lvl & 16) { // Sanity checking
00247   }
00248   if (debug_lvl & 64) {
00249     if (from == 0) { // Constructor
00250       cout << IdSrc << endl;
00251       cout << IdHdr << endl;
00252     }
00253   }
00254 }
00255 }