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

FGJSBBase.cpp

00001 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00002 
00003  Module:       FGJSBBase.cpp
00004  Author:       Jon S. Berndt
00005  Date started: 07/01/01
00006  Purpose:      Encapsulates the JSBBase object
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 FUNCTIONAL DESCRIPTION
00028 --------------------------------------------------------------------------------
00029 
00030 HISTORY
00031 --------------------------------------------------------------------------------
00032 07/01/01  JSB  Created
00033 
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 INCLUDES
00036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00037 
00038 #define BASE
00039 
00040 #include "FGJSBBase.h"
00041 #include <iostream>
00042 #include <sstream>
00043 #include <cstdlib>
00044 
00045 namespace JSBSim {
00046 
00047 static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.36 2013/01/25 13:39:11 jberndt Exp $";
00048 static const char *IdHdr = ID_JSBBASE;
00049 
00050 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00051 CLASS IMPLEMENTATION
00052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00053 
00054 #ifndef _MSC_VER
00055     char FGJSBBase::highint[5]  = {27, '[', '1', 'm', '\0'      };
00056     char FGJSBBase::halfint[5]  = {27, '[', '2', 'm', '\0'      };
00057     char FGJSBBase::normint[6]  = {27, '[', '2', '2', 'm', '\0' };
00058     char FGJSBBase::reset[5]    = {27, '[', '0', 'm', '\0'      };
00059     char FGJSBBase::underon[5]  = {27, '[', '4', 'm', '\0'      };
00060     char FGJSBBase::underoff[6] = {27, '[', '2', '4', 'm', '\0' };
00061     char FGJSBBase::fgblue[6]   = {27, '[', '3', '4', 'm', '\0' };
00062     char FGJSBBase::fgcyan[6]   = {27, '[', '3', '6', 'm', '\0' };
00063     char FGJSBBase::fgred[6]    = {27, '[', '3', '1', 'm', '\0' };
00064     char FGJSBBase::fggreen[6]  = {27, '[', '3', '2', 'm', '\0' };
00065     char FGJSBBase::fgdef[6]    = {27, '[', '3', '9', 'm', '\0' };
00066 #else
00067     char FGJSBBase::highint[5]  = {'\0' };
00068     char FGJSBBase::halfint[5]  = {'\0' };
00069     char FGJSBBase::normint[6]  = {'\0' };
00070     char FGJSBBase::reset[5]    = {'\0' };
00071     char FGJSBBase::underon[5]  = {'\0' };
00072     char FGJSBBase::underoff[6] = {'\0' };
00073     char FGJSBBase::fgblue[6]   = {'\0' };
00074     char FGJSBBase::fgcyan[6]   = {'\0' };
00075     char FGJSBBase::fgred[6]    = {'\0' };
00076     char FGJSBBase::fggreen[6]  = {'\0' };
00077     char FGJSBBase::fgdef[6]    = {'\0' };
00078 #endif
00079 
00080 const double FGJSBBase::radtodeg = 57.295779513082320876798154814105;
00081 const double FGJSBBase::degtorad = 0.017453292519943295769236907684886;
00082 const double FGJSBBase::hptoftlbssec = 550.0;
00083 const double FGJSBBase::psftoinhg = 0.014138;
00084 const double FGJSBBase::psftopa = 47.88;
00085 const double FGJSBBase::fpstokts = 0.592484;
00086 const double FGJSBBase::ktstofps = 1.68781;
00087 const double FGJSBBase::inchtoft = 0.08333333;
00088 const double FGJSBBase::in3tom3 = 1.638706E-5;
00089 const double FGJSBBase::m3toft3 = 1.0/(fttom*fttom*fttom);
00090 const double FGJSBBase::inhgtopa = 3386.38;
00091 const double FGJSBBase::fttom = 0.3048;
00092 double FGJSBBase::Reng = 1716.56;   // Gas constant for Air (ft-lb/slug-R)
00093 double FGJSBBase::Rstar = 1545.348; // Universal gas constant
00094 double FGJSBBase::Mair = 28.9645;   //
00095 const double FGJSBBase::SHRatio = 1.40;
00096 
00097 // Note that definition of lbtoslug by the inverse of slugtolb and not
00098 // to a different constant you can also get from some tables will make
00099 // lbtoslug*slugtolb == 1 up to the magnitude of roundoff. So converting from
00100 // slug to lb and back will yield to the original value you started with up
00101 // to the magnitude of roundoff.
00102 // Taken from units gnu commandline tool
00103 const double FGJSBBase::slugtolb = 32.174049;
00104 const double FGJSBBase::lbtoslug = 1.0/slugtolb;
00105 const double FGJSBBase::kgtolb = 2.20462;
00106 const double FGJSBBase::kgtoslug = 0.06852168;
00107 
00108 const string FGJSBBase::needed_cfg_version = "2.0";
00109 const string FGJSBBase::JSBSim_version = "1.0 " __DATE__ " " __TIME__ ;
00110 
00111 std::queue <FGJSBBase::Message> FGJSBBase::Messages;
00112 FGJSBBase::Message FGJSBBase::localMsg;
00113 unsigned int FGJSBBase::messageId = 0;
00114 
00115 short FGJSBBase::debug_lvl  = 1;
00116 
00117 using std::cerr;
00118 using std::cout;
00119 using std::endl;
00120 
00121 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00122 
00123 void FGJSBBase::PutMessage(const Message& msg)
00124 {
00125   Messages.push(msg);
00126 }
00127 
00128 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00129 
00130 void FGJSBBase::PutMessage(const string& text)
00131 {
00132   Message msg;
00133   msg.text = text;
00134   msg.messageId = messageId++;
00135   msg.subsystem = "FDM";
00136   msg.type = Message::eText;
00137   Messages.push(msg);
00138 }
00139 
00140 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00141 
00142 void FGJSBBase::PutMessage(const string& text, bool bVal)
00143 {
00144   Message msg;
00145   msg.text = text;
00146   msg.messageId = messageId++;
00147   msg.subsystem = "FDM";
00148   msg.type = Message::eBool;
00149   msg.bVal = bVal;
00150   Messages.push(msg);
00151 }
00152 
00153 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00154 
00155 void FGJSBBase::PutMessage(const string& text, int iVal)
00156 {
00157   Message msg;
00158   msg.text = text;
00159   msg.messageId = messageId++;
00160   msg.subsystem = "FDM";
00161   msg.type = Message::eInteger;
00162   msg.iVal = iVal;
00163   Messages.push(msg);
00164 }
00165 
00166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00167 
00168 void FGJSBBase::PutMessage(const string& text, double dVal)
00169 {
00170   Message msg;
00171   msg.text = text;
00172   msg.messageId = messageId++;
00173   msg.subsystem = "FDM";
00174   msg.type = Message::eDouble;
00175   msg.dVal = dVal;
00176   Messages.push(msg);
00177 }
00178 
00179 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00180 
00181 int FGJSBBase::SomeMessages(void)
00182 {
00183   return !Messages.empty();
00184 }
00185 
00186 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00187 
00188 void FGJSBBase::ProcessMessage(void)
00189 {
00190   if (Messages.empty()) return;
00191   localMsg = Messages.front();
00192 
00193   while (Messages.size() > 0) {
00194       switch (localMsg.type) {
00195       case JSBSim::FGJSBBase::Message::eText:
00196         cout << localMsg.messageId << ": " << localMsg.text << endl;
00197         break;
00198       case JSBSim::FGJSBBase::Message::eBool:
00199         cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.bVal << endl;
00200         break;
00201       case JSBSim::FGJSBBase::Message::eInteger:
00202         cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.iVal << endl;
00203         break;
00204       case JSBSim::FGJSBBase::Message::eDouble:
00205         cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.dVal << endl;
00206         break;
00207       default:
00208         cerr << "Unrecognized message type." << endl;
00209         break;
00210       }
00211       Messages.pop();
00212       if (Messages.size() > 0) localMsg = Messages.front();
00213       else break;
00214   }
00215 
00216 }
00217 
00218 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00219 
00220 FGJSBBase::Message* FGJSBBase::ProcessNextMessage(void)
00221 {
00222   if (Messages.empty()) return NULL;
00223   localMsg = Messages.front();
00224 
00225   Messages.pop();
00226   return &localMsg;
00227 }
00228 
00229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00230 
00231 void FGJSBBase::disableHighLighting(void)
00232 {
00233   highint[0]='\0';
00234   halfint[0]='\0';
00235   normint[0]='\0';
00236   reset[0]='\0';
00237   underon[0]='\0';
00238   underoff[0]='\0';
00239   fgblue[0]='\0';
00240   fgcyan[0]='\0';
00241   fgred[0]='\0';
00242   fggreen[0]='\0';
00243   fgdef[0]='\0';
00244 }
00245 
00246 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00247 
00248 string FGJSBBase::CreateIndexedPropertyName(const string& Property, int index)
00249 {
00250   std::ostringstream buf;
00251   buf << Property << '[' << index << ']';
00252   return buf.str();
00253 }
00254 
00255 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00256 
00257 double FGJSBBase::GaussianRandomNumber(void)
00258 {
00259   static double V1, V2, S;
00260   static int phase = 0;
00261   double X;
00262 
00263   if (phase == 0) {
00264     V1 = V2 = S = X = 0.0;
00265 
00266     do {
00267       double U1 = (double)rand() / RAND_MAX;
00268       double U2 = (double)rand() / RAND_MAX;
00269 
00270       V1 = 2 * U1 - 1;
00271       V2 = 2 * U2 - 1;
00272       S = V1 * V1 + V2 * V2;
00273     } while(S >= 1 || S == 0);
00274 
00275     X = V1 * sqrt(-2 * log(S) / S);
00276   } else
00277     X = V2 * sqrt(-2 * log(S) / S);
00278 
00279   phase = 1 - phase;
00280 
00281   return X;
00282 }
00283 
00284 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00285 
00286 double FGJSBBase::VcalibratedFromMach(double mach, double p, double psl, double rhosl)
00287 {
00288   double pt,A;
00289 
00290   if (mach < 0) mach=0;
00291   if (mach < 1)    //calculate total pressure assuming isentropic flow
00292     pt=p*pow((1 + 0.2*mach*mach),3.5);
00293   else {
00294     // shock in front of pitot tube, we'll assume its normal and use
00295     // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
00296     // pressure behind the shock to the static pressure in front of
00297     // the normal shock assumption should not be a bad one -- most supersonic
00298     // aircraft place the pitot probe out front so that it is the forward
00299     // most point on the aircraft.  The real shock would, of course, take
00300     // on something like the shape of a rounded-off cone but, here again,
00301     // the assumption should be good since the opening of the pitot probe
00302     // is very small and, therefore, the effects of the shock curvature
00303     // should be small as well. AFAIK, this approach is fairly well accepted
00304     // within the aerospace community
00305 
00306     // The denominator below is zero for Mach ~ 0.38, for which
00307     // we'll never be here, so we're safe
00308 
00309     pt = p*166.92158*pow(mach,7.0)/pow(7*mach*mach-1,2.5);
00310   }
00311 
00312   A = pow(((pt-p)/psl+1),0.28571);
00313   return sqrt(7*psl/rhosl*(A-1));
00314 }
00315 
00316 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00317 
00318 double FGJSBBase::MachFromVcalibrated(double vcas, double p, double psl, double rhosl)
00319 {
00320   double pt = p + psl*(pow(1+vcas*vcas*rhosl/(7.0*psl),3.5)-1);
00321 
00322   if (pt/p < 1.89293)
00323     return sqrt(5.0*(pow(pt/p, 0.2857143) -1)); // Mach < 1
00324   else {
00325     // Mach >= 1
00326     double mach = sqrt(0.77666*pt/p); // Initial guess is based on a quadratic approximation of the Rayleigh formula
00327     double delta = 1.;
00328     double target = pt/(166.92158*p);
00329     int iter = 0;
00330 
00331     // Find the root with Newton-Raphson. Since the differential is never zero,
00332     // the function is monotonic and has only one root with a multiplicity of one.
00333     // Convergence is certain.
00334     while (delta > 1E-5 && iter < 10) {
00335       double m2 = mach*mach; // Mach^2
00336       double m6 = m2*m2*m2;  // Mach^6
00337       delta = mach*m6/pow(7.0*m2-1.0,2.5) - target;
00338       double diff = 7.0*m6*(2.0*m2-1)/pow(7.0*m2-1.0,3.5); // Never zero when Mach >= 1
00339       mach -= delta/diff;
00340       iter++;
00341     }
00342 
00343     return mach;
00344   }
00345 }
00346 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00347 
00348 } // namespace JSBSim
00349