JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
FGOutputTextFile.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGOutputTextFile.cpp
4  Author: Bertrand Coconnier
5  Date started: 09/17/11
6  Purpose: Manage output of sim parameters to a text file
7  Called by: FGOutput
8 
9  ------------- Copyright (C) 2011 Bertrand Coconnier -------------
10 
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU Lesser General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15 
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19  details.
20 
21  You should have received a copy of the GNU Lesser General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25  Further information about the GNU Lesser General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27 
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This is the place where you create output routines to dump data for perusal
31 later.
32 
33 HISTORY
34 --------------------------------------------------------------------------------
35 09/17/11 BC Created
36 
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 INCLUDES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40 
41 #include <cstring>
42 #include <cstdlib>
43 #include <iomanip>
44 #include <sstream>
45 
46 #include "FGOutputTextFile.h"
47 #include "FGFDMExec.h"
48 #include "models/FGAerodynamics.h"
49 #include "models/FGAccelerations.h"
50 #include "models/FGAircraft.h"
51 #include "models/FGAtmosphere.h"
52 #include "models/FGAuxiliary.h"
53 #include "models/FGPropulsion.h"
54 #include "models/FGMassBalance.h"
55 #include "models/FGPropagate.h"
56 #include "models/FGGroundReactions.h"
57 #include "models/FGExternalReactions.h"
58 #include "models/FGBuoyantForces.h"
59 #include "models/FGFCS.h"
60 #include "models/atmosphere/FGWinds.h"
61 #include "input_output/FGXMLElement.h"
62 
63 using namespace std;
64 
65 namespace JSBSim {
66 
67 IDENT(IdSrc,"$Id: FGOutputTextFile.cpp,v 1.13 2017/02/25 14:23:18 bcoconni Exp $");
68 IDENT(IdHdr,ID_OUTPUTTEXTFILE);
69 
70 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 CLASS IMPLEMENTATION
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
73 
74 bool FGOutputTextFile::Load(Element* el)
75 {
76  if(!FGOutputFile::Load(el))
77  return false;
78 
79 // PreLoad(el, PropertyManager);
80 
81  string type = el->GetAttributeValue("type");
82  string delim;
83  if (type == "TABULAR") {
84  delim = "\t";
85  } else {
86  delim = ",";
87  }
88 
89  SetDelimiter(delim);
90 
91  return true;
92 }
93 
94 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95 
96 bool FGOutputTextFile::OpenFile(void)
97 {
98  datafile.clear();
99  datafile.open(Filename);
100  if (!datafile) {
101  cerr << endl << fgred << highint << "ERROR: unable to open the file "
102  << reset << Filename.c_str() << endl
103  << fgred << highint << " => Output to this file is disabled."
104  << reset << endl << endl;
105  Disable();
106  return false;
107  }
108 
109  string scratch = "";
110  streambuf* buffer = datafile.rdbuf();
111  ostream outstream(buffer);
112 
113  outstream.precision(10);
114 
115  outstream << "Time";
116  if (SubSystems & ssSimulation) {
117  // Nothing here, yet
118  }
119  if (SubSystems & ssAerosurfaces) {
120  outstream << delimeter;
121  outstream << "Aileron Command (norm)" + delimeter;
122  outstream << "Elevator Command (norm)" + delimeter;
123  outstream << "Rudder Command (norm)" + delimeter;
124  outstream << "Flap Command (norm)" + delimeter;
125  outstream << "Left Aileron Position (deg)" + delimeter;
126  outstream << "Right Aileron Position (deg)" + delimeter;
127  outstream << "Elevator Position (deg)" + delimeter;
128  outstream << "Rudder Position (deg)" + delimeter;
129  outstream << "Flap Position (deg)";
130  }
131  if (SubSystems & ssRates) {
132  outstream << delimeter;
133  outstream << "P (deg/s)" + delimeter + "Q (deg/s)" + delimeter + "R (deg/s)" + delimeter;
134  outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)" + delimeter;
135  outstream << "P_{inertial} (deg/s)" + delimeter + "Q_{inertial} (deg/s)" + delimeter + "R_{inertial} (deg/s)";
136  }
137  if (SubSystems & ssVelocities) {
138  outstream << delimeter;
139  outstream << "q bar (psf)" + delimeter;
140  outstream << "Reynolds Number" + delimeter;
141  outstream << "V_{Total} (ft/s)" + delimeter;
142  outstream << "V_{Inertial} (ft/s)" + delimeter;
143  outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
144  outstream << "UdotBody" + delimeter + "VdotBody" + delimeter + "WdotBody" + delimeter;
145  outstream << "UdotBody_i" + delimeter + "VdotBody_i" + delimeter + "WdotBody_i" + delimeter;
146  outstream << "BodyAccel_X" + delimeter + "BodyAccel_Y" + delimeter + "BodyAccel_Z" + delimeter;
147  outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter;
148  outstream << "V_{X_{inertial}} (ft/s)" + delimeter + "V_{Y_{inertial}} (ft/s)" + delimeter + "V_{Z_{inertial}} (ft/s)" + delimeter;
149  outstream << "V_{X_{ecef}} (ft/s)" + delimeter + "V_{Y_{ecef}} (ft/s)" + delimeter + "V_{Z_{ecef}} (ft/s)" + delimeter;
150  outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)";
151  }
152  if (SubSystems & ssForces) {
153  outstream << delimeter;
154  outstream << "F_{Drag} (lbs)" + delimeter + "F_{Side} (lbs)" + delimeter + "F_{Lift} (lbs)" + delimeter;
155  outstream << "L/D" + delimeter;
156  outstream << "F_{Aero x} (lbs)" + delimeter + "F_{Aero y} (lbs)" + delimeter + "F_{Aero z} (lbs)" + delimeter;
157  outstream << "F_{Prop x} (lbs)" + delimeter + "F_{Prop y} (lbs)" + delimeter + "F_{Prop z} (lbs)" + delimeter;
158  outstream << "F_{Gear x} (lbs)" + delimeter + "F_{Gear y} (lbs)" + delimeter + "F_{Gear z} (lbs)" + delimeter;
159  outstream << "F_{Ext x} (lbs)" + delimeter + "F_{Ext y} (lbs)" + delimeter + "F_{Ext z} (lbs)" + delimeter;
160  outstream << "F_{Buoyant x} (lbs)" + delimeter + "F_{Buoyant y} (lbs)" + delimeter + "F_{Buoyant z} (lbs)" + delimeter;
161  outstream << "F_{Weight x} (lbs)" + delimeter + "F_{Weight y} (lbs)" + delimeter + "F_{Weight z} (lbs)" + delimeter;
162  outstream << "F_{Total x} (lbs)" + delimeter + "F_{Total y} (lbs)" + delimeter + "F_{Total z} (lbs)";
163  }
164  if (SubSystems & ssMoments) {
165  outstream << delimeter;
166  outstream << "L_{Aero} (ft-lbs)" + delimeter + "M_{Aero} (ft-lbs)" + delimeter + "N_{Aero} (ft-lbs)" + delimeter;
167  outstream << "L_{Aero MRC} (ft-lbs)" + delimeter + "M_{Aero MRC} (ft-lbs)" + delimeter + "N_{Aero MRC} (ft-lbs)" + delimeter;
168  outstream << "L_{Prop} (ft-lbs)" + delimeter + "M_{Prop} (ft-lbs)" + delimeter + "N_{Prop} (ft-lbs)" + delimeter;
169  outstream << "L_{Gear} (ft-lbs)" + delimeter + "M_{Gear} (ft-lbs)" + delimeter + "N_{Gear} (ft-lbs)" + delimeter;
170  outstream << "L_{ext} (ft-lbs)" + delimeter + "M_{ext} (ft-lbs)" + delimeter + "N_{ext} (ft-lbs)" + delimeter;
171  outstream << "L_{Buoyant} (ft-lbs)" + delimeter + "M_{Buoyant} (ft-lbs)" + delimeter + "N_{Buoyant} (ft-lbs)" + delimeter;
172  outstream << "L_{Total} (ft-lbs)" + delimeter + "M_{Total} (ft-lbs)" + delimeter + "N_{Total} (ft-lbs)";
173  }
174  if (SubSystems & ssAtmosphere) {
175  outstream << delimeter;
176  outstream << "Rho (slugs/ft^3)" + delimeter;
177  outstream << "Absolute Viscosity" + delimeter;
178  outstream << "Kinematic Viscosity" + delimeter;
179  outstream << "Temperature (R)" + delimeter;
180  outstream << "P_{SL} (psf)" + delimeter;
181  outstream << "P_{Ambient} (psf)" + delimeter;
182  outstream << "Turbulence Magnitude (ft/sec)" + delimeter;
183  outstream << "Turbulence X Direction (deg)" + delimeter;
184  outstream << "Wind V_{North} (ft/s)" + delimeter + "Wind V_{East} (ft/s)" + delimeter + "Wind V_{Down} (ft/s)" + delimeter;
185  outstream << "Roll Turbulence (deg/sec)" + delimeter + "Pitch Turbulence (deg/sec)" + delimeter + "Yaw Turbulence (deg/sec)";
186  }
187  if (SubSystems & ssMassProps) {
188  outstream << delimeter;
189  outstream << "I_{xx}" + delimeter;
190  outstream << "I_{xy}" + delimeter;
191  outstream << "I_{xz}" + delimeter;
192  outstream << "I_{yx}" + delimeter;
193  outstream << "I_{yy}" + delimeter;
194  outstream << "I_{yz}" + delimeter;
195  outstream << "I_{zx}" + delimeter;
196  outstream << "I_{zy}" + delimeter;
197  outstream << "I_{zz}" + delimeter;
198  outstream << "Mass" + delimeter;
199  outstream << "Weight" + delimeter;
200  outstream << "X_{cg}" + delimeter + "Y_{cg}" + delimeter + "Z_{cg}";
201  }
202  if (SubSystems & ssPropagate) {
203  outstream << delimeter;
204  outstream << "Altitude ASL (ft)" + delimeter;
205  outstream << "Altitude AGL (ft)" + delimeter;
206  outstream << "Phi (deg)" + delimeter + "Theta (deg)" + delimeter + "Psi (deg)" + delimeter;
207  outstream << "Q(1)_{LOCAL}" + delimeter + "Q(2)_{LOCAL}" + delimeter + "Q(3)_{LOCAL}" + delimeter + "Q(4)_{LOCAL}" + delimeter;
208  outstream << "Q(1)_{ECEF}" + delimeter + "Q(2)_{ECEF}" + delimeter + "Q(3)_{ECEF}" + delimeter + "Q(4)_{ECEF}" + delimeter;
209  outstream << "Q(1)_{ECI}" + delimeter + "Q(2)_{ECI}" + delimeter + "Q(3)_{ECI}" + delimeter + "Q(4)_{ECI}" + delimeter;
210  outstream << "Alpha (deg)" + delimeter;
211  outstream << "Beta (deg)" + delimeter;
212  outstream << "Latitude (deg)" + delimeter;
213  outstream << "Latitude Geodetic (deg)" + delimeter;
214  outstream << "Longitude (deg)" + delimeter;
215  outstream << "X_{ECI} (ft)" + delimeter + "Y_{ECI} (ft)" + delimeter + "Z_{ECI} (ft)" + delimeter;
216  outstream << "X_{ECEF} (ft)" + delimeter + "Y_{ECEF} (ft)" + delimeter + "Z_{ECEF} (ft)" + delimeter;
217  outstream << "Earth Position Angle (deg)" + delimeter;
218  outstream << "Distance AGL (ft)" + delimeter;
219  outstream << "Terrain Elevation (ft)";
220  }
221  if (SubSystems & ssAeroFunctions) {
222  scratch = Aerodynamics->GetAeroFunctionStrings(delimeter);
223  if (scratch.length() != 0) outstream << delimeter << scratch;
224  }
225  if (SubSystems & ssFCS) {
226  scratch = FCS->GetComponentStrings(delimeter);
227  if (scratch.length() != 0) outstream << delimeter << scratch;
228  }
229  if (SubSystems & ssGroundReactions) {
230  outstream << delimeter;
231  outstream << GroundReactions->GetGroundReactionStrings(delimeter);
232  }
233  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
234  outstream << delimeter;
235  outstream << Propulsion->GetPropulsionStrings(delimeter);
236  }
237  if (OutputProperties.size() > 0) {
238  for (unsigned int i=0;i<OutputProperties.size();i++) {
239  if (OutputCaptions[i].size() > 0) {
240  outstream << delimeter << OutputCaptions[i];
241  } else {
242  outstream << delimeter << OutputProperties[i]->GetFullyQualifiedName();
243  }
244  }
245  }
246 
247  if (PreFunctions.size() > 0) {
248  for (unsigned int i=0;i<PreFunctions.size();i++) {
249  outstream << delimeter << PreFunctions[i]->GetName();
250  }
251  }
252 
253  outstream << endl;
254  outstream.flush();
255 
256  return true;
257 }
258 
259 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 
261 void FGOutputTextFile::Print(void)
262 {
263  streambuf* buffer;
264  string scratch = Filename.utf8Str();
265 
266  if (to_upper(scratch) == "COUT") {
267  buffer = cout.rdbuf();
268  } else {
269  buffer = datafile.rdbuf();
270  }
271 
272  ostream outstream(buffer);
273 
274  outstream.precision(10);
275 
276  outstream << FDMExec->GetSimTime();
277  if (SubSystems & ssSimulation) {
278  }
279  if (SubSystems & ssAerosurfaces) {
280  outstream << delimeter;
281  outstream << FCS->GetDaCmd() << delimeter;
282  outstream << FCS->GetDeCmd() << delimeter;
283  outstream << FCS->GetDrCmd() << delimeter;
284  outstream << FCS->GetDfCmd() << delimeter;
285  outstream << FCS->GetDaLPos(ofDeg) << delimeter;
286  outstream << FCS->GetDaRPos(ofDeg) << delimeter;
287  outstream << FCS->GetDePos(ofDeg) << delimeter;
288  outstream << FCS->GetDrPos(ofDeg) << delimeter;
289  outstream << FCS->GetDfPos(ofDeg);
290  }
291  if (SubSystems & ssRates) {
292  outstream << delimeter;
293  outstream << (radtodeg*Propagate->GetPQR()).Dump(delimeter) << delimeter;
294  outstream << (radtodeg*Accelerations->GetPQRdot()).Dump(delimeter) << delimeter;
295  outstream << (radtodeg*Propagate->GetPQRi()).Dump(delimeter);
296  }
297  if (SubSystems & ssVelocities) {
298  outstream << delimeter;
299  outstream << Auxiliary->Getqbar() << delimeter;
300  outstream << Auxiliary->GetReynoldsNumber() << delimeter;
301  outstream << setprecision(12) << Auxiliary->GetVt() << delimeter;
302  outstream << Propagate->GetInertialVelocityMagnitude() << delimeter;
303  outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
304  outstream << setprecision(12) << Accelerations->GetUVWdot().Dump(delimeter) << delimeter;
305  outstream << setprecision(12) << Accelerations->GetUVWidot().Dump(delimeter) << delimeter;
306  outstream << setprecision(12) << Accelerations->GetBodyAccel().Dump(delimeter) << delimeter;
307  outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
308  outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter;
309  outstream << Propagate->GetECEFVelocity().Dump(delimeter) << delimeter;
310  outstream << Propagate->GetVel().Dump(delimeter);
311  outstream.precision(10);
312  }
313  if (SubSystems & ssForces) {
314  outstream << delimeter;
315  outstream << Aerodynamics->GetvFw().Dump(delimeter) << delimeter;
316  outstream << Aerodynamics->GetLoD() << delimeter;
317  outstream << Aerodynamics->GetForces().Dump(delimeter) << delimeter;
318  outstream << Propulsion->GetForces().Dump(delimeter) << delimeter;
319  outstream << Accelerations->GetGroundForces().Dump(delimeter) << delimeter;
320  outstream << ExternalReactions->GetForces().Dump(delimeter) << delimeter;
321  outstream << BuoyantForces->GetForces().Dump(delimeter) << delimeter;
322  outstream << Accelerations->GetWeight().Dump(delimeter) << delimeter;
323  outstream << Accelerations->GetForces().Dump(delimeter);
324  }
325  if (SubSystems & ssMoments) {
326  outstream << delimeter;
327  outstream << Aerodynamics->GetMoments().Dump(delimeter) << delimeter;
328  outstream << Aerodynamics->GetMomentsMRC().Dump(delimeter) << delimeter;
329  outstream << Propulsion->GetMoments().Dump(delimeter) << delimeter;
330  outstream << Accelerations->GetGroundMoments().Dump(delimeter) << delimeter;
331  outstream << ExternalReactions->GetMoments().Dump(delimeter) << delimeter;
332  outstream << BuoyantForces->GetMoments().Dump(delimeter) << delimeter;
333  outstream << Accelerations->GetMoments().Dump(delimeter);
334  }
335  if (SubSystems & ssAtmosphere) {
336  outstream << delimeter;
337  outstream << Atmosphere->GetDensity() << delimeter;
338  outstream << Atmosphere->GetAbsoluteViscosity() << delimeter;
339  outstream << Atmosphere->GetKinematicViscosity() << delimeter;
340  outstream << Atmosphere->GetTemperature() << delimeter;
341  outstream << Atmosphere->GetPressureSL() << delimeter;
342  outstream << Atmosphere->GetPressure() << delimeter;
343  outstream << Winds->GetTurbMagnitude() << delimeter;
344  outstream << Winds->GetTurbDirection() << delimeter;
345  outstream << Winds->GetTotalWindNED().Dump(delimeter) << delimeter;
346  outstream << (Winds->GetTurbPQR()*radtodeg).Dump(delimeter);
347  }
348  if (SubSystems & ssMassProps) {
349  outstream << delimeter;
350  outstream << MassBalance->GetJ().Dump(delimeter) << delimeter;
351  outstream << MassBalance->GetMass() << delimeter;
352  outstream << MassBalance->GetWeight() << delimeter;
353  outstream << MassBalance->GetXYZcg().Dump(delimeter);
354  }
355  if (SubSystems & ssPropagate) {
356  outstream.precision(14);
357  outstream << delimeter;
358  outstream << Propagate->GetAltitudeASL() << delimeter;
359  outstream << Propagate->GetDistanceAGL() << delimeter;
360  outstream << (radtodeg*Propagate->GetEuler()).Dump(delimeter) << delimeter;
361  outstream << Propagate->GetQuaternion().Dump(delimeter) << delimeter;
362  FGQuaternion Qec = Propagate->GetQuaternionECEF();
363  outstream << Qec.Dump(delimeter) << delimeter;
364  outstream << Propagate->GetQuaternionECI().Dump(delimeter) << delimeter;
365  outstream << Auxiliary->Getalpha(inDegrees) << delimeter;
366  outstream << Auxiliary->Getbeta(inDegrees) << delimeter;
367  outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter;
368  outstream << Propagate->GetLocation().GetGeodLatitudeDeg() << delimeter;
369  outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter;
370  outstream.precision(18);
371  outstream << ((FGColumnVector3)Propagate->GetInertialPosition()).Dump(delimeter) << delimeter;
372  outstream << ((FGColumnVector3)Propagate->GetLocation()).Dump(delimeter) << delimeter;
373  outstream.precision(14);
374  outstream << Propagate->GetEarthPositionAngleDeg() << delimeter;
375  outstream << Propagate->GetDistanceAGL() << delimeter;
376  outstream << Propagate->GetTerrainElevation();
377  outstream.precision(10);
378  }
379  if (SubSystems & ssAeroFunctions) {
380  scratch = Aerodynamics->GetAeroFunctionValues(delimeter);
381  if (scratch.length() != 0) outstream << delimeter << scratch;
382  }
383  if (SubSystems & ssFCS) {
384  scratch = FCS->GetComponentValues(delimeter);
385  if (scratch.length() != 0) outstream << delimeter << scratch;
386  }
387  if (SubSystems & ssGroundReactions) {
388  outstream << delimeter;
389  outstream << GroundReactions->GetGroundReactionValues(delimeter);
390  }
391  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
392  outstream << delimeter;
393  outstream << Propulsion->GetPropulsionValues(delimeter);
394  }
395 
396  outstream.precision(18);
397  for (unsigned int i=0;i<OutputProperties.size();i++) {
398  outstream << delimeter << OutputProperties[i]->getDoubleValue();
399  }
400  for (unsigned int i=0;i<PreFunctions.size();i++) {
401  outstream << delimeter << PreFunctions[i]->getDoubleValue();
402  }
403  outstream.precision(10);
404 
405  outstream << endl;
406  outstream.flush();
407 }
408 }
Models the Quaternion representation of rotations.
Definition: FGQuaternion.h:92
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
STL namespace.
This class implements a 3 element column vector.
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
Definition: FGFDMExec.h:533