]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGAircraft.cpp
JSBSim tweaks.
[flightgear.git] / src / FDM / JSBSim / FGAircraft.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2  
3  Module:       FGAircraft.cpp
4  Author:       Jon S. Berndt
5  Date started: 12/12/98                                   
6  Purpose:      Encapsulates an aircraft
7  Called by:    FGFDMExec
8
9  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
10  
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU 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 General Public License for more
19  details.
20  
21  You should have received a copy of the GNU 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 General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27  
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 Models the aircraft reactions and forces. This class is instantiated by the
31 FGFDMExec class and scheduled as an FDM entry. LoadAircraft() is supplied with a
32 name of a valid, registered aircraft, and the data file is parsed.
33  
34 HISTORY
35 --------------------------------------------------------------------------------
36 12/12/98   JSB   Created
37 04/03/99   JSB   Changed Aero() method to correct body axis force calculation
38                  from wind vector. Fix provided by Tony Peden.
39 05/03/99   JSB   Changed (for the better?) the way configurations are read in.
40 9/17/99     TP   Combined force and moment functions. Added aero reference 
41                  point to config file. Added calculations for moments due to 
42                  difference in cg and aero reference point
43  
44 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 COMMENTS, REFERENCES,  and NOTES
46 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47
48 [1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
49       Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
50       School, January 1994
51 [2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
52       JSC 12960, July 1977
53 [3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
54       NASA-Ames", NASA CR-2497, January 1975
55 [4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
56       Wiley & Sons, 1979 ISBN 0-471-03032-5
57 [5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
58       1982 ISBN 0-471-08936-2
59  
60 The aerodynamic coefficients used in this model are:
61  
62 Longitudinal
63   CL0 - Reference lift at zero alpha
64   CD0 - Reference drag at zero alpha
65   CDM - Drag due to Mach
66   CLa - Lift curve slope (w.r.t. alpha)
67   CDa - Drag curve slope (w.r.t. alpha)
68   CLq - Lift due to pitch rate
69   CLM - Lift due to Mach
70   CLadt - Lift due to alpha rate
71  
72   Cmadt - Pitching Moment due to alpha rate
73   Cm0 - Reference Pitching moment at zero alpha
74   Cma - Pitching moment slope (w.r.t. alpha)
75   Cmq - Pitch damping (pitch moment due to pitch rate)
76   CmM - Pitch Moment due to Mach
77  
78 Lateral
79   Cyb - Side force due to sideslip
80   Cyr - Side force due to yaw rate
81  
82   Clb - Dihedral effect (roll moment due to sideslip)
83   Clp - Roll damping (roll moment due to roll rate)
84   Clr - Roll moment due to yaw rate
85   Cnb - Weathercocking stability (yaw moment due to sideslip)
86   Cnp - Rudder adverse yaw (yaw moment due to roll rate)
87   Cnr - Yaw damping (yaw moment due to yaw rate)
88  
89 Control
90   CLDe - Lift due to elevator
91   CDDe - Drag due to elevator
92   CyDr - Side force due to rudder
93   CyDa - Side force due to aileron
94  
95   CmDe - Pitch moment due to elevator
96   ClDa - Roll moment due to aileron
97   ClDr - Roll moment due to rudder
98   CnDr - Yaw moment due to rudder
99   CnDa - Yaw moment due to aileron
100  
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 INCLUDES
103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
104
105 #include <sys/stat.h>
106 #include <sys/types.h>
107
108 #ifdef FGFS
109 #  ifndef __BORLANDC__
110 #    include <simgear/compiler.h>
111 #  endif
112 #  ifdef SG_HAVE_STD_INCLUDES
113 #    include <cmath>
114 #  else
115 #    include <math.h>
116 #  endif
117 #else
118 #  include <cmath>
119 #endif
120
121 #include "FGAircraft.h"
122 #include "FGMassBalance.h"
123 #include "FGInertial.h"
124 #include "FGAerodynamics.h"
125 #include "FGTranslation.h"
126 #include "FGRotation.h"
127 #include "FGAtmosphere.h"
128 #include "FGState.h"
129 #include "FGFDMExec.h"
130 #include "FGFCS.h"
131 #include "FGPosition.h"
132 #include "FGAuxiliary.h"
133 #include "FGOutput.h"
134
135 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 DEFINITIONS
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
138
139 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 GLOBAL DATA
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
142
143 static const char *IdSrc = "$Id$";
144 static const char *IdHdr = ID_AIRCRAFT;
145
146 extern char highint[5];
147 extern char halfint[5];
148 extern char normint[6];
149 extern char reset[5];
150 extern char underon[5];
151 extern char underoff[6];
152 extern char fgblue[6];
153 extern char fgcyan[6];
154 extern char fgred[6];
155 extern char fggreen[6];
156 extern char fgdef[6];
157
158 extern short debug_lvl;
159
160 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161 CLASS IMPLEMENTATION
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
163
164 FGAircraft::FGAircraft(FGFDMExec* fdmex) : FGModel(fdmex),
165     vMoments(3),
166     vForces(3),
167     vXYZrp(3),
168     vXYZep(3),
169     vEuler(3),
170     vDXYZcg(3),
171     vAeroBodyForces(3)
172 {
173   Name = "FGAircraft";
174
175   GearUp = false;
176
177   alphaclmin = alphaclmax = 0;
178
179   if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
180 }
181
182
183 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184
185
186 FGAircraft::~FGAircraft()
187 {
188   if (debug_lvl & 2) cout << "Destroyed:    FGAircraft" << endl;
189 }
190
191 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192
193 bool FGAircraft::LoadAircraft(string aircraft_path, string engine_path, string fname) {
194   string path;
195   string filename;
196   string aircraftCfgFileName;
197   string token;
198
199   AircraftPath = aircraft_path;
200   EnginePath = engine_path;
201
202 # ifndef macintosh
203   aircraftCfgFileName = AircraftPath + "/" + fname + "/" + fname + ".xml";
204 # else
205   aircraftCfgFileName = AircraftPath + ";" + fname + ";" + fname + ".xml";
206 # endif
207
208   FGConfigFile AC_cfg(aircraftCfgFileName);
209   if (!AC_cfg.IsOpen()) return false;
210
211   ReadPrologue(&AC_cfg);
212
213   while ((AC_cfg.GetNextConfigLine() != string("EOF")) &&
214          (token = AC_cfg.GetValue()) != string("/FDM_CONFIG")) {
215     if (token == "METRICS") {
216       if (debug_lvl > 0) cout << fgcyan << "\n  Reading Metrics" << fgdef << endl;
217       ReadMetrics(&AC_cfg);
218     } else if (token == "AERODYNAMICS") {
219       if (debug_lvl > 0) cout << fgcyan << "\n  Reading Aerodynamics" << fgdef << endl;
220       ReadAerodynamics(&AC_cfg);
221     } else if (token == "UNDERCARRIAGE") {
222       if (debug_lvl > 0) cout << fgcyan << "\n  Reading Landing Gear" << fgdef << endl;
223       ReadUndercarriage(&AC_cfg);
224     } else if (token == "PROPULSION") {
225       if (debug_lvl > 0) cout << fgcyan << "\n  Reading Propulsion" << fgdef << endl;
226       ReadPropulsion(&AC_cfg);
227     } else if (token == "FLIGHT_CONTROL") {
228       if (debug_lvl > 0) cout << fgcyan << "\n  Reading Flight Control" << fgdef << endl;
229       ReadFlightControls(&AC_cfg);
230     } else if (token == "OUTPUT") {
231       if (debug_lvl > 0) cout << fgcyan << "\n  Reading Output directives" << fgdef << endl;
232       ReadOutput(&AC_cfg);
233     }
234   }
235
236   return true;
237 }
238
239 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240
241 bool FGAircraft::Run(void)
242 {
243   if (!FGModel::Run()) {                 // if false then execute this Run()
244     GetState();
245
246     vForces.InitMatrix();
247     vMoments.InitMatrix();
248
249     FMProp();
250     FMAero();
251     FMMass();
252     FMGear();
253
254     return false;
255   } else {                               // skip Run() execution this time
256     return true;
257   }
258 }
259
260 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
262 void FGAircraft::FMAero(void)
263 {
264     vForces += Aerodynamics->GetForces();
265     vMoments += Aerodynamics->GetMoments();
266 }
267
268 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269
270 void FGAircraft::FMGear(void)
271 {
272   if ( !GearUp ) {
273     vector <FGLGear>::iterator iGear = lGear.begin();
274     while (iGear != lGear.end()) {
275       vForces  += iGear->Force();
276       vMoments += iGear->Moment();
277       iGear++;
278     }
279   } else {
280     // Crash Routine
281   }
282 }
283
284 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285
286 void FGAircraft::FMMass(void)
287 {
288   vForces += Inertial->GetForces();
289 }
290
291 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292
293 void FGAircraft::FMProp(void)
294 {
295   vForces += Propulsion->GetForces();
296   vMoments += Propulsion->GetMoments();
297 }
298
299 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300
301 void FGAircraft::GetState(void)
302 {
303   dt = State->Getdt();
304
305   alpha = Translation->Getalpha();
306   beta = Translation->Getbeta();
307   vEuler = Rotation->GetEuler();
308 }
309
310 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311
312 void FGAircraft::ReadMetrics(FGConfigFile* AC_cfg)
313 {
314   string token = "";
315   string parameter;
316   float EW, bixx, biyy, bizz, bixz, biyz;
317   FGColumnVector vbaseXYZcg(3);
318
319   AC_cfg->GetNextConfigLine();
320
321   while ((token = AC_cfg->GetValue()) != string("/METRICS")) {
322     *AC_cfg >> parameter;
323     if (parameter == string("AC_WINGAREA")) {
324       *AC_cfg >> WingArea;
325       if (debug_lvl > 0) cout << "    WingArea: " << WingArea  << endl;
326     } else if (parameter == "AC_WINGSPAN") {
327       *AC_cfg >> WingSpan;
328       if (debug_lvl > 0) cout << "    WingSpan: " << WingSpan  << endl;
329     } else if (parameter == "AC_CHORD") {
330       *AC_cfg >> cbar;
331       if (debug_lvl > 0) cout << "    Chord: " << cbar << endl;
332     } else if (parameter == "AC_IXX") {
333       *AC_cfg >> bixx;
334       if (debug_lvl > 0) cout << "    baseIxx: " << bixx << endl;
335       MassBalance->SetBaseIxx(bixx);
336     } else if (parameter == "AC_IYY") {
337       *AC_cfg >> biyy;
338       if (debug_lvl > 0) cout << "    baseIyy: " << biyy << endl;
339       MassBalance->SetBaseIyy(biyy);
340     } else if (parameter == "AC_IZZ") {
341       *AC_cfg >> bizz;
342       if (debug_lvl > 0) cout << "    baseIzz: " << bizz << endl;
343       MassBalance->SetBaseIzz(bizz);
344     } else if (parameter == "AC_IXZ") {
345       *AC_cfg >> bixz;
346       if (debug_lvl > 0) cout << "    baseIxz: " << bixz  << endl;
347       MassBalance->SetBaseIxz(bixz);
348     } else if (parameter == "AC_IYZ") {
349       *AC_cfg >> biyz;
350       if (debug_lvl > 0) cout << "    baseIyz: " << biyz  << endl;
351       MassBalance->SetBaseIyz(biyz);
352     } else if (parameter == "AC_EMPTYWT") {
353       *AC_cfg >> EW;
354       MassBalance->SetEmptyWeight(EW);
355       if (debug_lvl > 0) cout << "    EmptyWeight: " << EW  << endl;
356     } else if (parameter == "AC_CGLOC") {
357       *AC_cfg >> vbaseXYZcg(eX) >> vbaseXYZcg(eY) >> vbaseXYZcg(eZ);
358       MassBalance->SetBaseCG(vbaseXYZcg);
359       if (debug_lvl > 0) cout << "    CG (x, y, z): " << vbaseXYZcg << endl;
360     } else if (parameter == "AC_EYEPTLOC") {
361       *AC_cfg >> vXYZep(eX) >> vXYZep(eY) >> vXYZep(eZ);
362       if (debug_lvl > 0) cout << "    Eyepoint (x, y, z): " << vXYZep << endl;
363     } else if (parameter == "AC_AERORP") {
364       *AC_cfg >> vXYZrp(eX) >> vXYZrp(eY) >> vXYZrp(eZ);
365       if (debug_lvl > 0) cout << "    Ref Pt (x, y, z): " << vXYZrp << endl;
366     } else if (parameter == "AC_ALPHALIMITS") {
367       *AC_cfg >> alphaclmin >> alphaclmax;
368       if (debug_lvl > 0) cout << "    Maximum Alpha: " << alphaclmax
369              << "    Minimum Alpha: " << alphaclmin
370              << endl;
371     }
372   }
373 }
374
375 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376
377 void FGAircraft::ReadPropulsion(FGConfigFile* AC_cfg) {
378   if (!Propulsion->LoadPropulsion(AC_cfg)) {
379     cerr << "Propulsion not successfully loaded" << endl;
380   }
381 }
382
383 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384
385 void FGAircraft::ReadFlightControls(FGConfigFile* AC_cfg) {
386   if (!FCS->LoadFCS(AC_cfg)) {
387     cerr << "Flight Controls not successfully loaded" << endl;
388   }
389 }
390
391 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392
393 void FGAircraft::ReadAerodynamics(FGConfigFile* AC_cfg)
394 {
395   if (!Aerodynamics->LoadAerodynamics(AC_cfg)) {
396     cerr << "Aerodynamics not successfully loaded" << endl;
397   }
398
399 }
400
401 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402
403 void FGAircraft::ReadUndercarriage(FGConfigFile* AC_cfg) {
404   string token;
405
406   AC_cfg->GetNextConfigLine();
407
408   while ((token = AC_cfg->GetValue()) != string("/UNDERCARRIAGE")) {
409     lGear.push_back(FGLGear(AC_cfg, FDMExec));
410   }
411 }
412
413 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414
415 void FGAircraft::ReadOutput(FGConfigFile* AC_cfg) {
416   string token, parameter;
417   int OutRate = 0;
418   int subsystems = 0;
419
420   token = AC_cfg->GetValue("NAME");
421   Output->SetFilename(token);
422   token = AC_cfg->GetValue("TYPE");
423   Output->SetType(token);
424   AC_cfg->GetNextConfigLine();
425
426   while ((token = AC_cfg->GetValue()) != string("/OUTPUT")) {
427     *AC_cfg >> parameter;
428     if (parameter == "RATE_IN_HZ") *AC_cfg >> OutRate;
429     if (parameter == "SIMULATION") {
430       *AC_cfg >> parameter;
431       if (parameter == "ON") subsystems += ssSimulation;
432     }
433     if (parameter == "AEROSURFACES") {
434       *AC_cfg >> parameter;
435       if (parameter == "ON") subsystems += ssAerosurfaces;
436     }
437     if (parameter == "RATES") {
438       *AC_cfg >> parameter;
439       if (parameter == "ON") subsystems += ssRates;
440     }
441     if (parameter == "VELOCITIES") {
442       *AC_cfg >> parameter;
443       if (parameter == "ON") subsystems += ssVelocities;
444     }
445     if (parameter == "FORCES") {
446       *AC_cfg >> parameter;
447       if (parameter == "ON") subsystems += ssForces;
448     }
449     if (parameter == "MOMENTS") {
450       *AC_cfg >> parameter;
451       if (parameter == "ON") subsystems += ssMoments;
452     }
453     if (parameter == "ATMOSPHERE") {
454       *AC_cfg >> parameter;
455       if (parameter == "ON") subsystems += ssAtmosphere;
456     }
457     if (parameter == "MASSPROPS") {
458       *AC_cfg >> parameter;
459       if (parameter == "ON") subsystems += ssMassProps;
460     }
461     if (parameter == "POSITION") {
462       *AC_cfg >> parameter;
463       if (parameter == "ON") subsystems += ssPosition;
464     }
465     if (parameter == "COEFFICIENTS") {
466       *AC_cfg >> parameter;
467       if (parameter == "ON") subsystems += ssCoefficients;
468     }
469     if (parameter == "GROUND_REACTIONS") {
470       *AC_cfg >> parameter;
471       if (parameter == "ON") subsystems += ssGroundReactions;
472     }
473     if (parameter == "FCS") {
474       *AC_cfg >> parameter;
475       if (parameter == "ON") subsystems += ssFCS;
476     }
477     if (parameter == "PROPULSION") {
478       *AC_cfg >> parameter;
479       if (parameter == "ON") subsystems += ssPropulsion;
480     }
481   }
482
483   Output->SetSubsystems(subsystems);
484
485   OutRate = OutRate>120?120:(OutRate<0?0:OutRate);
486   Output->SetRate( (int)(0.5 + 1.0/(State->Getdt()*OutRate)) );
487 }
488
489 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490
491 void FGAircraft::ReadPrologue(FGConfigFile* AC_cfg) {
492   string token = AC_cfg->GetValue();
493   string scratch;
494   AircraftName = AC_cfg->GetValue("NAME");
495   if (debug_lvl > 0) cout << underon << "Reading Aircraft Configuration File"
496             << underoff << ": " << highint << AircraftName << normint << endl;
497   scratch = AC_cfg->GetValue("VERSION").c_str();
498
499   CFGVersion = AC_cfg->GetValue("VERSION");
500
501   if (debug_lvl > 0)
502     cout << "                            Version: " << highint << CFGVersion
503                                                              << normint << endl;
504   if (CFGVersion != string(NEEDED_CFG_VERSION)) {
505     cerr << endl << fgred << "YOU HAVE AN INCOMPATIBLE CFG FILE FOR THIS AIRCRAFT."
506             " RESULTS WILL BE UNPREDICTABLE !!" << endl;
507     cerr << "Current version needed is: " << NEEDED_CFG_VERSION << endl;
508     cerr << "         You have version: " << CFGVersion << endl << fgdef << endl;
509   }
510 }
511
512 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513
514 string FGAircraft::GetGroundReactionStrings(void) {
515   string GroundReactionStrings = "";
516   bool firstime = true;
517
518   for (unsigned int i=0;i<lGear.size();i++) {
519     if (!firstime) GroundReactionStrings += ", ";
520     GroundReactionStrings += (lGear[i].GetName() + "_WOW, ");
521     GroundReactionStrings += (lGear[i].GetName() + "_compressLength, ");
522     GroundReactionStrings += (lGear[i].GetName() + "_compressSpeed, ");
523     GroundReactionStrings += (lGear[i].GetName() + "_Force");
524
525     firstime = false;
526   }
527
528   return GroundReactionStrings;
529 }
530
531 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532
533 string FGAircraft::GetGroundReactionValues(void) {
534   char buff[20];
535   string GroundReactionValues = "";
536
537   bool firstime = true;
538
539   for (unsigned int i=0;i<lGear.size();i++) {
540     if (!firstime) GroundReactionValues += ", ";
541     GroundReactionValues += string( lGear[i].GetWOW()?"1":"0" ) + ", ";
542     GroundReactionValues += (string(gcvt(lGear[i].GetCompLen(),    5, buff)) + ", ");
543     GroundReactionValues += (string(gcvt(lGear[i].GetCompVel(),    6, buff)) + ", ");
544     GroundReactionValues += (string(gcvt(lGear[i].GetCompForce(), 10, buff)));
545
546     firstime = false;
547   }
548
549   return GroundReactionValues;
550 }
551
552 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553
554 void FGAircraft::Debug(void)
555 {
556     //TODO: Add your source code here
557 }
558