JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGJSBBase.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGJSBBase.cpp
4  Author: Jon S. Berndt
5  Date started: 07/01/01
6  Purpose: Encapsulates the JSBBase object
7 
8  ------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.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
12  Software Foundation; either version 2 of the License, or (at your option) any
13  later 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
21  with this program; if not, write to the Free Software Foundation, Inc., 59
22  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24  Further information about the GNU Lesser General Public License can also be
25  found on the world wide web at http://www.gnu.org.
26 
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29 
30 HISTORY
31 --------------------------------------------------------------------------------
32 07/01/01 JSB Created
33 
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 INCLUDES
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37 
38 #define BASE
39 
40 #include "FGJSBBase.h"
41 #include "models/FGAtmosphere.h"
42 
43 using namespace std;
44 
45 namespace JSBSim {
46 
47 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 CLASS IMPLEMENTATION
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50 
51 #ifndef _MSC_VER
52  char FGJSBBase::highint[5] = {27, '[', '1', 'm', '\0' };
53  char FGJSBBase::halfint[5] = {27, '[', '2', 'm', '\0' };
54  char FGJSBBase::normint[6] = {27, '[', '2', '2', 'm', '\0' };
55  char FGJSBBase::reset[5] = {27, '[', '0', 'm', '\0' };
56  char FGJSBBase::underon[5] = {27, '[', '4', 'm', '\0' };
57  char FGJSBBase::underoff[6] = {27, '[', '2', '4', 'm', '\0' };
58  char FGJSBBase::fgblue[6] = {27, '[', '3', '4', 'm', '\0' };
59  char FGJSBBase::fgcyan[6] = {27, '[', '3', '6', 'm', '\0' };
60  char FGJSBBase::fgred[6] = {27, '[', '3', '1', 'm', '\0' };
61  char FGJSBBase::fggreen[6] = {27, '[', '3', '2', 'm', '\0' };
62  char FGJSBBase::fgdef[6] = {27, '[', '3', '9', 'm', '\0' };
63 #else
64  char FGJSBBase::highint[5] = {'\0' };
65  char FGJSBBase::halfint[5] = {'\0' };
66  char FGJSBBase::normint[6] = {'\0' };
67  char FGJSBBase::reset[5] = {'\0' };
68  char FGJSBBase::underon[5] = {'\0' };
69  char FGJSBBase::underoff[6] = {'\0' };
70  char FGJSBBase::fgblue[6] = {'\0' };
71  char FGJSBBase::fgcyan[6] = {'\0' };
72  char FGJSBBase::fgred[6] = {'\0' };
73  char FGJSBBase::fggreen[6] = {'\0' };
74  char FGJSBBase::fgdef[6] = {'\0' };
75 #endif
76 
77 const string FGJSBBase::needed_cfg_version = "2.0";
78 const string FGJSBBase::JSBSim_version = JSBSIM_VERSION " " __DATE__ " " __TIME__ ;
79 
80 queue <FGJSBBase::Message> FGJSBBase::Messages;
81 FGJSBBase::Message FGJSBBase::localMsg;
82 unsigned int FGJSBBase::messageId = 0;
83 
84 int FGJSBBase::gaussian_random_number_phase = 0;
85 
86 short FGJSBBase::debug_lvl = 1;
87 
88 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 
90 void FGJSBBase::PutMessage(const Message& msg)
91 {
92  Messages.push(msg);
93 }
94 
95 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96 
97 void FGJSBBase::PutMessage(const string& text)
98 {
99  Message msg;
100  msg.text = text;
101  msg.messageId = messageId++;
102  msg.subsystem = "FDM";
103  msg.type = Message::eText;
104  Messages.push(msg);
105 }
106 
107 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 
109 void FGJSBBase::PutMessage(const string& text, bool bVal)
110 {
111  Message msg;
112  msg.text = text;
113  msg.messageId = messageId++;
114  msg.subsystem = "FDM";
115  msg.type = Message::eBool;
116  msg.bVal = bVal;
117  Messages.push(msg);
118 }
119 
120 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 
122 void FGJSBBase::PutMessage(const string& text, int iVal)
123 {
124  Message msg;
125  msg.text = text;
126  msg.messageId = messageId++;
127  msg.subsystem = "FDM";
128  msg.type = Message::eInteger;
129  msg.iVal = iVal;
130  Messages.push(msg);
131 }
132 
133 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134 
135 void FGJSBBase::PutMessage(const string& text, double dVal)
136 {
137  Message msg;
138  msg.text = text;
139  msg.messageId = messageId++;
140  msg.subsystem = "FDM";
141  msg.type = Message::eDouble;
142  msg.dVal = dVal;
143  Messages.push(msg);
144 }
145 
146 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147 
148 void FGJSBBase::ProcessMessage(void)
149 {
150  if (Messages.empty()) return;
151  localMsg = Messages.front();
152 
153  while (SomeMessages()) {
154  switch (localMsg.type) {
155  case JSBSim::FGJSBBase::Message::eText:
156  cout << localMsg.messageId << ": " << localMsg.text << endl;
157  break;
158  case JSBSim::FGJSBBase::Message::eBool:
159  cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.bVal << endl;
160  break;
161  case JSBSim::FGJSBBase::Message::eInteger:
162  cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.iVal << endl;
163  break;
164  case JSBSim::FGJSBBase::Message::eDouble:
165  cout << localMsg.messageId << ": " << localMsg.text << " " << localMsg.dVal << endl;
166  break;
167  default:
168  cerr << "Unrecognized message type." << endl;
169  break;
170  }
171  Messages.pop();
172  if (SomeMessages()) localMsg = Messages.front();
173  else break;
174  }
175 
176 }
177 
178 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 
180 FGJSBBase::Message* FGJSBBase::ProcessNextMessage(void)
181 {
182  if (Messages.empty()) return NULL;
183  localMsg = Messages.front();
184 
185  Messages.pop();
186  return &localMsg;
187 }
188 
189 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 
191 void FGJSBBase::disableHighLighting(void)
192 {
193  highint[0]='\0';
194  halfint[0]='\0';
195  normint[0]='\0';
196  reset[0]='\0';
197  underon[0]='\0';
198  underoff[0]='\0';
199  fgblue[0]='\0';
200  fgcyan[0]='\0';
201  fgred[0]='\0';
202  fggreen[0]='\0';
203  fgdef[0]='\0';
204 }
205 
206 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 
208 string FGJSBBase::CreateIndexedPropertyName(const string& Property, int index)
209 {
210  ostringstream buf;
211  buf << Property << '[' << index << ']';
212  return buf.str();
213 }
214 
215 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216 
217 double FGJSBBase::GaussianRandomNumber(void)
218 {
219  static double V1, V2, S;
220  double X;
221 
222  if (gaussian_random_number_phase == 0) {
223  V1 = V2 = S = X = 0.0;
224 
225  do {
226  double U1 = (double)rand() / RAND_MAX;
227  double U2 = (double)rand() / RAND_MAX;
228 
229  V1 = 2 * U1 - 1;
230  V2 = 2 * U2 - 1;
231  S = V1 * V1 + V2 * V2;
232  } while(S >= 1 || S == 0);
233 
234  X = V1 * sqrt(-2 * log(S) / S);
235  } else
236  X = V2 * sqrt(-2 * log(S) / S);
237 
238  gaussian_random_number_phase = 1 - gaussian_random_number_phase;
239 
240  return X;
241 }
242 
243 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 
245 double FGJSBBase::PitotTotalPressure(double mach, double p)
246 {
247  if (mach < 0) return p;
248  if (mach < 1) //calculate total pressure assuming isentropic flow
249  return p*pow((1 + 0.2*mach*mach),3.5);
250  else {
251  // shock in front of pitot tube, we'll assume its normal and use
252  // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
253  // pressure behind the shock to the static pressure in front of
254  // the normal shock assumption should not be a bad one -- most supersonic
255  // aircraft place the pitot probe out front so that it is the forward
256  // most point on the aircraft. The real shock would, of course, take
257  // on something like the shape of a rounded-off cone but, here again,
258  // the assumption should be good since the opening of the pitot probe
259  // is very small and, therefore, the effects of the shock curvature
260  // should be small as well. AFAIK, this approach is fairly well accepted
261  // within the aerospace community
262 
263  // The denominator below is zero for Mach ~ 0.38, for which
264  // we'll never be here, so we're safe
265 
266  return p*166.92158009316827*pow(mach,7.0)/pow(7*mach*mach-1,2.5);
267  }
268 }
269 
270 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 
272 // Based on the formulas in the US Air Force Aircraft Performance Flight Testing
273 // Manual (AFFTC-TIH-99-01). In particular sections 4.6 to 4.8.
274 
275 double FGJSBBase::MachFromImpactPressure(double qc, double p)
276 {
277  double A = qc / p + 1;
278  double M = sqrt(5.0*(pow(A, 1. / 3.5) - 1)); // Equation (4.12)
279 
280  if (M > 1.0)
281  for (unsigned int i = 0; i<10; i++)
282  M = 0.8812848543473311*sqrt(A*pow(1 - 1.0 / (7.0*M*M), 2.5)); // Equation (4.17)
283 
284  return M;
285 }
286 
287 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 
289 double FGJSBBase::VcalibratedFromMach(double mach, double p)
290 {
291  double asl = FGAtmosphere::StdDaySLsoundspeed;
292  double psl = FGAtmosphere::StdDaySLpressure;
293  double qc = PitotTotalPressure(mach, p) - p;
294 
295  return asl * MachFromImpactPressure(qc, psl);
296 }
297 
298 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299 
300 double FGJSBBase::MachFromVcalibrated(double vcas, double p)
301 {
302  double asl = FGAtmosphere::StdDaySLsoundspeed;
303  double psl = FGAtmosphere::StdDaySLpressure;
304  double qc = PitotTotalPressure(vcas / asl, psl) - psl;
305 
306  return MachFromImpactPressure(qc, p);
307 }
308 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 
310 } // namespace JSBSim
311 
JSBSim::FGJSBBase::Message
JSBSim Message structure.
Definition: FGJSBBase.h:87