PageRenderTime 125ms CodeModel.GetById 12ms app.highlight 104ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FDM/JSBSim/models/FGOutput.cpp

https://bitbucket.org/tomp/fg-test
C++ | 1127 lines | 917 code | 111 blank | 99 comment | 240 complexity | 443387ae5d985b1dc1ecc2879fefb77c MD5 | raw file
   1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2
   3 Module:       FGOutput.cpp
   4 Author:       Jon Berndt
   5 Date started: 12/02/98
   6 Purpose:      Manage output of sim parameters to file or stdout
   7 Called by:    FGSimExec
   8
   9 ------------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) -------------
  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
  28FUNCTIONAL DESCRIPTION
  29--------------------------------------------------------------------------------
  30This is the place where you create output routines to dump data for perusal
  31later.
  32
  33HISTORY
  34--------------------------------------------------------------------------------
  3512/02/98   JSB   Created
  3611/09/07   HDW   Added FlightGear Socket Interface
  37
  38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  39INCLUDES
  40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  41
  42#include "FGOutput.h"
  43#include "FGState.h"
  44#include "FGFDMExec.h"
  45#include "FGAtmosphere.h"
  46#include "FGFCS.h"
  47#include "FGAerodynamics.h"
  48#include "FGGroundReactions.h"
  49#include "FGExternalReactions.h"
  50#include "FGBuoyantForces.h"
  51#include "FGAircraft.h"
  52#include "FGMassBalance.h"
  53#include "FGPropagate.h"
  54#include "FGAuxiliary.h"
  55#include "FGInertial.h"
  56#include "FGPropulsion.h"   //access to FGEngine, FGTank
  57#include "models/propulsion/FGPiston.h"
  58#include <fstream>
  59#include <iomanip>
  60#include <cstring>
  61
  62#include "input_output/net_fdm.hxx"
  63
  64#if defined(WIN32) && !defined(__CYGWIN__)
  65#  include <windows.h>
  66#else
  67#  include <netinet/in.h>       // htonl() ntohl()
  68#endif
  69
  70static const int endianTest = 1;
  71#define isLittleEndian (*((char *) &endianTest ) != 0)
  72
  73namespace JSBSim {
  74
  75static const char *IdSrc = "$Id$";
  76static const char *IdHdr = ID_OUTPUT;
  77
  78// (stolen from FGFS native_fdm.cxx)
  79// The function htond is defined this way due to the way some
  80// processors and OSes treat floating point values.  Some will raise
  81// an exception whenever a "bad" floating point value is loaded into a
  82// floating point register.  Solaris is notorious for this, but then
  83// so is LynxOS on the PowerPC.  By translating the data in place,
  84// there is no need to load a FP register with the "corruped" floating
  85// point value.  By doing the BIG_ENDIAN test, I can optimize the
  86// routine for big-endian processors so it can be as efficient as
  87// possible
  88static void htond (double &x)
  89{
  90    if ( isLittleEndian ) {
  91        int    *Double_Overlay;
  92        int     Holding_Buffer;
  93
  94        Double_Overlay = (int *) &x;
  95        Holding_Buffer = Double_Overlay [0];
  96
  97        Double_Overlay [0] = htonl (Double_Overlay [1]);
  98        Double_Overlay [1] = htonl (Holding_Buffer);
  99    } else {
 100        return;
 101    }
 102}
 103
 104// Float version
 105static void htonf (float &x)
 106{
 107    if ( isLittleEndian ) {
 108        int    *Float_Overlay;
 109        int     Holding_Buffer;
 110
 111        Float_Overlay = (int *) &x;
 112        Holding_Buffer = Float_Overlay [0];
 113
 114        Float_Overlay [0] = htonl (Holding_Buffer);
 115    } else {
 116        return;
 117    }
 118}
 119
 120
 121/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 122CLASS IMPLEMENTATION
 123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 124
 125FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex)
 126{
 127  Name = "FGOutput";
 128  sFirstPass = dFirstPass = true;
 129  socket = 0;
 130  flightGearSocket = 0;
 131  runID_postfix = 0;
 132  Type = otNone;
 133  SubSystems = 0;
 134  enabled = true;
 135  StartNewFile = false;
 136  delimeter = ", ";
 137  BaseFilename = Filename = "";
 138  DirectivesFile = "";
 139  output_file_name = "";
 140
 141  memset(&fgSockBuf, 0x00, sizeof(fgSockBuf));
 142
 143  Debug(0);
 144}
 145
 146//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 147
 148FGOutput::~FGOutput()
 149{
 150  delete socket;
 151  delete flightGearSocket;
 152  OutputProperties.clear();
 153  Debug(1);
 154}
 155
 156//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 157
 158bool FGOutput::InitModel(void)
 159{
 160  char fname[1000] = "";
 161
 162  if (!FGModel::InitModel()) return false;
 163
 164  if (Filename.size() > 0 && StartNewFile) {
 165    int idx = BaseFilename.find_last_of(".");
 166    int len = BaseFilename.length();
 167    string extension = "";
 168    if (idx != string::npos) {
 169      extension = BaseFilename.substr(idx, len-idx);
 170      len -= extension.length();
 171    }
 172    sprintf(fname, "%s_%d%s", BaseFilename.substr(0,len).c_str(), runID_postfix++, extension.c_str());
 173    Filename = string(fname);
 174    datafile.close();
 175    StartNewFile = false;
 176    dFirstPass = true;
 177  }
 178
 179  return true;
 180}
 181
 182//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 183
 184bool FGOutput::Run(void)
 185{
 186  if (FGModel::Run()) return true;
 187
 188  if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) {
 189    if (Type == otSocket) {
 190      SocketOutput();
 191    } else if (Type == otFlightGear) {
 192      FlightGearSocketOutput();
 193    } else if (Type == otCSV || Type == otTab) {
 194      DelimitedOutput(Filename);
 195    } else if (Type == otTerminal) {
 196      // Not done yet
 197    } else if (Type == otNone) {
 198      // Do nothing
 199    } else {
 200      // Not a valid type of output
 201    }
 202  }
 203  return false;
 204}
 205
 206//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 207
 208void FGOutput::SetType(string type)
 209{
 210  if (type == "CSV") {
 211    Type = otCSV;
 212    delimeter = ", ";
 213  } else if (type == "TABULAR") {
 214    Type = otTab;
 215    delimeter = "\t";
 216  } else if (type == "SOCKET") {
 217    Type = otSocket;
 218  } else if (type == "FLIGHTGEAR") {
 219    Type = otFlightGear;
 220  } else if (type == "TERMINAL") {
 221    Type = otTerminal;
 222  } else if (type != string("NONE")) {
 223    Type = otUnknown;
 224    cerr << "Unknown type of output specified in config file" << endl;
 225  }
 226}
 227
 228//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 229
 230void FGOutput::DelimitedOutput(string fname)
 231{
 232  streambuf* buffer;
 233  string scratch = "";
 234
 235  if (fname == "COUT" || fname == "cout") {
 236    buffer = cout.rdbuf();
 237  } else {
 238    if (!datafile.is_open()) datafile.open(fname.c_str());
 239    buffer = datafile.rdbuf();
 240  }
 241
 242  ostream outstream(buffer);
 243
 244  outstream.precision(10);
 245
 246  if (dFirstPass) {
 247    outstream << "Time";
 248    if (SubSystems & ssSimulation) {
 249      // Nothing here, yet
 250    }
 251    if (SubSystems & ssAerosurfaces) {
 252      outstream << delimeter;
 253      outstream << "Aileron Command (norm)" + delimeter;
 254      outstream << "Elevator Command (norm)" + delimeter;
 255      outstream << "Rudder Command (norm)" + delimeter;
 256      outstream << "Flap Command (norm)" + delimeter;
 257      outstream << "Left Aileron Position (deg)" + delimeter;
 258      outstream << "Right Aileron Position (deg)" + delimeter;
 259      outstream << "Elevator Position (deg)" + delimeter;
 260      outstream << "Rudder Position (deg)" + delimeter;
 261      outstream << "Flap Position (deg)";
 262    }
 263    if (SubSystems & ssRates) {
 264      outstream << delimeter;
 265      outstream << "P (deg/s)" + delimeter + "Q (deg/s)" + delimeter + "R (deg/s)" + delimeter;
 266      outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)";
 267    }
 268    if (SubSystems & ssVelocities) {
 269      outstream << delimeter;
 270      outstream << "q bar (psf)" + delimeter;
 271      outstream << "Reynolds Number" + delimeter;
 272      outstream << "V_{Total} (ft/s)" + delimeter;
 273      outstream << "V_{Inertial} (ft/s)" + delimeter;
 274      outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
 275      outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter;
 276      outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)";
 277    }
 278    if (SubSystems & ssForces) {
 279      outstream << delimeter;
 280      outstream << "F_{Drag} (lbs)" + delimeter + "F_{Side} (lbs)" + delimeter + "F_{Lift} (lbs)" + delimeter;
 281      outstream << "L/D" + delimeter;
 282      outstream << "F_{Aero x} (lbs)" + delimeter + "F_{Aero y} (lbs)" + delimeter + "F_{Aero z} (lbs)" + delimeter;
 283      outstream << "F_{Prop x} (lbs)" + delimeter + "F_{Prop y} (lbs)" + delimeter + "F_{Prop z} (lbs)" + delimeter;
 284      outstream << "F_{Gear x} (lbs)" + delimeter + "F_{Gear y} (lbs)" + delimeter + "F_{Gear z} (lbs)" + delimeter;
 285      outstream << "F_{Ext x} (lbs)" + delimeter + "F_{Ext y} (lbs)" + delimeter + "F_{Ext z} (lbs)" + delimeter;
 286      outstream << "F_{Buoyant x} (lbs)" + delimeter + "F_{Buoyant y} (lbs)" + delimeter + "F_{Buoyant z} (lbs)" + delimeter;
 287      outstream << "F_{Total x} (lbs)" + delimeter + "F_{Total y} (lbs)" + delimeter + "F_{Total z} (lbs)";
 288    }
 289    if (SubSystems & ssMoments) {
 290      outstream << delimeter;
 291      outstream << "L_{Aero} (ft-lbs)" + delimeter + "M_{Aero} ( ft-lbs)" + delimeter + "N_{Aero} (ft-lbs)" + delimeter;
 292      outstream << "L_{Prop} (ft-lbs)" + delimeter + "M_{Prop} (ft-lbs)" + delimeter + "N_{Prop} (ft-lbs)" + delimeter;
 293      outstream << "L_{Gear} (ft-lbs)" + delimeter + "M_{Gear} (ft-lbs)" + delimeter + "N_{Gear} (ft-lbs)" + delimeter;
 294      outstream << "L_{ext} (ft-lbs)" + delimeter + "M_{ext} (ft-lbs)" + delimeter + "N_{ext} (ft-lbs)" + delimeter;
 295      outstream << "L_{Buoyant} (ft-lbs)" + delimeter + "M_{Buoyant} (ft-lbs)" + delimeter + "N_{Buoyant} (ft-lbs)" + delimeter;
 296      outstream << "L_{Total} (ft-lbs)" + delimeter + "M_{Total} (ft-lbs)" + delimeter + "N_{Total} (ft-lbs)";
 297    }
 298    if (SubSystems & ssAtmosphere) {
 299      outstream << delimeter;
 300      outstream << "Rho (slugs/ft^3)" + delimeter;
 301      outstream << "Absolute Viscosity" + delimeter;
 302      outstream << "Kinematic Viscosity" + delimeter;
 303      outstream << "Temperature (R)" + delimeter;
 304      outstream << "P_{SL} (psf)" + delimeter;
 305      outstream << "P_{Ambient} (psf)" + delimeter;
 306      outstream << "Turbulence Magnitude (ft/sec)" + delimeter;
 307      outstream << "Turbulence X Direction (rad)" + delimeter + "Turbulence Y Direction (rad)" + delimeter + "Turbulence Z Direction (rad)" + delimeter;
 308      outstream << "Wind V_{North} (ft/s)" + delimeter + "Wind V_{East} (ft/s)" + delimeter + "Wind V_{Down} (ft/s)";
 309    }
 310    if (SubSystems & ssMassProps) {
 311      outstream << delimeter;
 312      outstream << "I_{xx}" + delimeter;
 313      outstream << "I_{xy}" + delimeter;
 314      outstream << "I_{xz}" + delimeter;
 315      outstream << "I_{yx}" + delimeter;
 316      outstream << "I_{yy}" + delimeter;
 317      outstream << "I_{yz}" + delimeter;
 318      outstream << "I_{zx}" + delimeter;
 319      outstream << "I_{zy}" + delimeter;
 320      outstream << "I_{zz}" + delimeter;
 321      outstream << "Mass" + delimeter;
 322      outstream << "X_{cg}" + delimeter + "Y_{cg}" + delimeter + "Z_{cg}";
 323    }
 324    if (SubSystems & ssPropagate) {
 325      outstream << delimeter;
 326      outstream << "Altitude ASL (ft)" + delimeter;
 327      outstream << "Altitude AGL (ft)" + delimeter;
 328      outstream << "Phi (deg)" + delimeter + "Theta (deg)" + delimeter + "Psi (deg)" + delimeter;
 329      outstream << "Alpha (deg)" + delimeter;
 330      outstream << "Beta (deg)" + delimeter;
 331      outstream << "Latitude (deg)" + delimeter;
 332      outstream << "Longitude (deg)" + delimeter;
 333      outstream << "ECEF X (ft)" + delimeter + "ECEF Y (ft)" + delimeter + "ECEF Z (ft)" + delimeter;
 334      outstream << "EPA (deg)" + delimeter;
 335      outstream << "Distance AGL (ft)" + delimeter;
 336      outstream << "Terrain Elevation (ft)";
 337    }
 338    if (SubSystems & ssCoefficients) {
 339      scratch = Aerodynamics->GetCoefficientStrings(delimeter);
 340      if (scratch.length() != 0) outstream << delimeter << scratch;
 341    }
 342    if (SubSystems & ssFCS) {
 343      scratch = FCS->GetComponentStrings(delimeter);
 344      if (scratch.length() != 0) outstream << delimeter << scratch;
 345    }
 346    if (SubSystems & ssGroundReactions) {
 347      outstream << delimeter;
 348      outstream << GroundReactions->GetGroundReactionStrings(delimeter);
 349    }
 350    if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
 351      outstream << delimeter;
 352      outstream << Propulsion->GetPropulsionStrings(delimeter);
 353    }
 354    if (OutputProperties.size() > 0) {
 355      for (unsigned int i=0;i<OutputProperties.size();i++) {
 356        outstream << delimeter << OutputProperties[i]->GetPrintableName();
 357      }
 358    }
 359
 360    outstream << endl;
 361    dFirstPass = false;
 362  }
 363
 364  outstream << State->Getsim_time();
 365  if (SubSystems & ssSimulation) {
 366  }
 367  if (SubSystems & ssAerosurfaces) {
 368    outstream << delimeter;
 369    outstream << FCS->GetDaCmd() << delimeter;
 370    outstream << FCS->GetDeCmd() << delimeter;
 371    outstream << FCS->GetDrCmd() << delimeter;
 372    outstream << FCS->GetDfCmd() << delimeter;
 373    outstream << FCS->GetDaLPos(ofDeg) << delimeter;
 374    outstream << FCS->GetDaRPos(ofDeg) << delimeter;
 375    outstream << FCS->GetDePos(ofDeg) << delimeter;
 376    outstream << FCS->GetDrPos(ofDeg) << delimeter;
 377    outstream << FCS->GetDfPos(ofDeg);
 378  }
 379  if (SubSystems & ssRates) {
 380    outstream << delimeter;
 381    outstream << (radtodeg*Propagate->GetPQR()).Dump(delimeter) << delimeter;
 382    outstream << (radtodeg*Propagate->GetPQRdot()).Dump(delimeter);
 383  }
 384  if (SubSystems & ssVelocities) {
 385    outstream << delimeter;
 386    outstream << Auxiliary->Getqbar() << delimeter;
 387    outstream << Auxiliary->GetReynoldsNumber() << delimeter;
 388    outstream << setprecision(12) << Auxiliary->GetVt() << delimeter;
 389    outstream << Propagate->GetInertialVelocityMagnitude() << delimeter;
 390    outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
 391    outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
 392    outstream << Propagate->GetVel().Dump(delimeter);
 393    outstream.precision(10);
 394  }
 395  if (SubSystems & ssForces) {
 396    outstream << delimeter;
 397    outstream << Aerodynamics->GetvFw() << delimeter;
 398    outstream << Aerodynamics->GetLoD() << delimeter;
 399    outstream << Aerodynamics->GetForces() << delimeter;
 400    outstream << Propulsion->GetForces() << delimeter;
 401    outstream << GroundReactions->GetForces() << delimeter;
 402    outstream << ExternalReactions->GetForces() << delimeter;
 403    outstream << BuoyantForces->GetForces() << delimeter;
 404    outstream << Aircraft->GetForces().Dump(delimeter);
 405  }
 406  if (SubSystems & ssMoments) {
 407    outstream << delimeter;
 408    outstream << Aerodynamics->GetMoments() << delimeter;
 409    outstream << Propulsion->GetMoments() << delimeter;
 410    outstream << GroundReactions->GetMoments() << delimeter;
 411    outstream << ExternalReactions->GetMoments() << delimeter;
 412    outstream << BuoyantForces->GetMoments() << delimeter;
 413    outstream << Aircraft->GetMoments().Dump(delimeter);
 414  }
 415  if (SubSystems & ssAtmosphere) {
 416    outstream << delimeter;
 417    outstream << Atmosphere->GetDensity() << delimeter;
 418    outstream << Atmosphere->GetAbsoluteViscosity() << delimeter;
 419    outstream << Atmosphere->GetKinematicViscosity() << delimeter;
 420    outstream << Atmosphere->GetTemperature() << delimeter;
 421    outstream << Atmosphere->GetPressureSL() << delimeter;
 422    outstream << Atmosphere->GetPressure() << delimeter;
 423    outstream << Atmosphere->GetTurbMagnitude() << delimeter;
 424    outstream << Atmosphere->GetTurbDirection().Dump(delimeter) << delimeter;
 425    outstream << Atmosphere->GetTotalWindNED().Dump(delimeter);
 426  }
 427  if (SubSystems & ssMassProps) {
 428    outstream << delimeter;
 429    outstream << MassBalance->GetJ() << delimeter;
 430    outstream << MassBalance->GetMass() << delimeter;
 431    outstream << MassBalance->GetXYZcg();
 432  }
 433  if (SubSystems & ssPropagate) {
 434    outstream.precision(14);
 435    outstream << delimeter;
 436    outstream << Propagate->GetAltitudeASL() << delimeter;
 437    outstream << Propagate->GetDistanceAGL() << delimeter;
 438    outstream << (radtodeg*Propagate->GetEuler()).Dump(delimeter) << delimeter;
 439    outstream << Auxiliary->Getalpha(inDegrees) << delimeter;
 440    outstream << Auxiliary->Getbeta(inDegrees) << delimeter;
 441    outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter;
 442    outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter;
 443    outstream.precision(18);
 444    outstream << ((FGColumnVector3)Propagate->GetLocation()).Dump(delimeter) << delimeter;
 445    outstream.precision(14);
 446    outstream << Inertial->GetEarthPositionAngleDeg() << delimeter;
 447    outstream << Propagate->GetDistanceAGL() << delimeter;
 448    outstream << Propagate->GetTerrainElevation();
 449    outstream.precision(10);
 450  }
 451  if (SubSystems & ssCoefficients) {
 452    scratch = Aerodynamics->GetCoefficientValues(delimeter);
 453    if (scratch.length() != 0) outstream << delimeter << scratch;
 454  }
 455  if (SubSystems & ssFCS) {
 456    scratch = FCS->GetComponentValues(delimeter);
 457    if (scratch.length() != 0) outstream << delimeter << scratch;
 458  }
 459  if (SubSystems & ssGroundReactions) {
 460    outstream << delimeter;
 461    outstream << GroundReactions->GetGroundReactionValues(delimeter);
 462  }
 463  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
 464    outstream << delimeter;
 465    outstream << Propulsion->GetPropulsionValues(delimeter);
 466  }
 467
 468  outstream.precision(18);
 469  for (unsigned int i=0;i<OutputProperties.size();i++) {
 470    outstream << delimeter << OutputProperties[i]->getDoubleValue();
 471  }
 472  outstream.precision(10);
 473
 474  outstream << endl;
 475  outstream.flush();
 476}
 477
 478//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 479
 480void FGOutput::SocketDataFill(FGNetFDM* net)
 481{
 482    unsigned int i;
 483
 484    // Version
 485    net->version = FG_NET_FDM_VERSION;
 486
 487    // Positions
 488    net->longitude = Propagate->GetLocation().GetLongitude(); // geodetic (radians)
 489    net->latitude  = Propagate->GetLocation().GetLatitude(); // geodetic (radians)
 490    net->altitude  = Propagate->GetAltitudeASL()*0.3048; // altitude, above sea level (meters)
 491    net->agl       = (float)(Propagate->GetDistanceAGL()*0.3048); // altitude, above ground level (meters)
 492
 493    net->phi       = (float)(Propagate->GetEuler(ePhi)); // roll (radians)
 494    net->theta     = (float)(Propagate->GetEuler(eTht)); // pitch (radians)
 495    net->psi       = (float)(Propagate->GetEuler(ePsi)); // yaw or true heading (radians)
 496
 497    net->alpha     = (float)(Auxiliary->Getalpha()); // angle of attack (radians)
 498    net->beta      = (float)(Auxiliary->Getbeta()); // side slip angle (radians)
 499
 500    // Velocities
 501    net->phidot     = (float)(Auxiliary->GetEulerRates(ePhi)); // roll rate (radians/sec)
 502    net->thetadot   = (float)(Auxiliary->GetEulerRates(eTht)); // pitch rate (radians/sec)
 503    net->psidot     = (float)(Auxiliary->GetEulerRates(ePsi)); // yaw rate (radians/sec)
 504    net->vcas       = (float)(Auxiliary->GetVcalibratedFPS()); // VCAS, ft/sec
 505    net->climb_rate = (float)(Propagate->Gethdot());           // altitude rate, ft/sec
 506    net->v_north    = (float)(Propagate->GetVel(eNorth));      // north vel in NED frame, fps
 507    net->v_east     = (float)(Propagate->GetVel(eEast));       // east vel in NED frame, fps
 508    net->v_down     = (float)(Propagate->GetVel(eDown));       // down vel in NED frame, fps
 509//---ADD METHOD TO CALCULATE THESE TERMS---
 510    net->v_wind_body_north = (float)(Propagate->GetVel(eNorth)); // north vel in NED relative to airmass, fps
 511    net->v_wind_body_east = (float)(Propagate->GetVel(eEast)); // east vel in NED relative to airmass, fps
 512    net->v_wind_body_down = (float)(Propagate->GetVel(eDown)); // down vel in NED relative to airmass, fps
 513
 514    // Accelerations
 515    net->A_X_pilot   = (float)(Auxiliary->GetPilotAccel(1));    // X body accel, ft/s/s
 516    net->A_Y_pilot   = (float)(Auxiliary->GetPilotAccel(2));    // Y body accel, ft/s/s
 517    net->A_Z_pilot   = (float)(Auxiliary->GetPilotAccel(3));    // Z body accel, ft/s/s
 518
 519    // Stall
 520    net->stall_warning = 0.0;  // 0.0 - 1.0 indicating the amount of stall
 521    net->slip_deg    = (float)(Auxiliary->Getbeta(inDegrees));  // slip ball deflection, deg
 522
 523    // Engine status
 524    net->num_engines = Propulsion->GetNumEngines(); // Number of valid engines
 525
 526    for (i=0; i<net->num_engines; i++) {
 527       if (Propulsion->GetEngine(i)->GetRunning())
 528          net->eng_state[i] = 2;       // Engine state running
 529       else if (Propulsion->GetEngine(i)->GetCranking())
 530          net->eng_state[i] = 1;       // Engine state cranking
 531       else
 532          net->eng_state[i] = 0;       // Engine state off
 533
 534       switch (Propulsion->GetEngine(i)->GetType()) {
 535       case (FGEngine::etRocket):
 536       break;
 537       case (FGEngine::etPiston):
 538          net->rpm[i]       = (float)(((FGPiston *)Propulsion->GetEngine(i))->getRPM());
 539          net->fuel_flow[i] = (float)(((FGPiston *)Propulsion->GetEngine(i))->getFuelFlow_gph());
 540          net->fuel_px[i]   = 0; // Fuel pressure, psi  (N/A in current model)
 541          net->egt[i]       = (float)(((FGPiston *)Propulsion->GetEngine(i))->GetEGT());
 542          net->cht[i]       = (float)(((FGPiston *)Propulsion->GetEngine(i))->getCylinderHeadTemp_degF());
 543          net->mp_osi[i]    = (float)(((FGPiston *)Propulsion->GetEngine(i))->getManifoldPressure_inHg());
 544          net->oil_temp[i]  = (float)(((FGPiston *)Propulsion->GetEngine(i))->getOilTemp_degF());
 545          net->oil_px[i]    = (float)(((FGPiston *)Propulsion->GetEngine(i))->getOilPressure_psi());
 546          net->tit[i]       = 0; // Turbine Inlet Temperature  (N/A for piston)
 547       break;
 548       case (FGEngine::etTurbine):
 549       break;
 550       case (FGEngine::etTurboprop):
 551       break;
 552       case (FGEngine::etElectric):
 553       break;
 554       case (FGEngine::etUnknown):
 555       break;
 556       }
 557    }
 558
 559
 560    // Consumables
 561    net->num_tanks = Propulsion->GetNumTanks();   // Max number of fuel tanks
 562
 563    for (i=0; i<net->num_tanks; i++) {
 564       net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents());
 565    }
 566
 567
 568    // Gear status
 569    net->num_wheels  = GroundReactions->GetNumGearUnits();
 570
 571    for (i=0; i<net->num_wheels; i++) {
 572       net->wow[i]              = GroundReactions->GetGearUnit(i)->GetWOW();
 573       if (GroundReactions->GetGearUnit(i)->GetGearUnitDown())
 574          net->gear_pos[i]      = 1;  //gear down, using FCS convention
 575       else
 576          net->gear_pos[i]      = 0;  //gear up, using FCS convention
 577       net->gear_steer[i]       = (float)(GroundReactions->GetGearUnit(i)->GetSteerNorm());
 578       net->gear_compression[i] = (float)(GroundReactions->GetGearUnit(i)->GetCompLen());
 579    }
 580
 581
 582    // Environment
 583    net->cur_time    = (long int)1234567890;	// Friday, Feb 13, 2009, 23:31:30 UTC (not processed by FGFS anyway)
 584    net->warp        = 0;                       // offset in seconds to unix time
 585    net->visibility  = 25000.0;                 // visibility in meters (for env. effects)
 586
 587
 588    // Control surface positions (normalized values)
 589    net->elevator          = (float)(FCS->GetDePos(ofNorm));    // Norm Elevator Pos, --
 590    net->elevator_trim_tab = (float)(FCS->GetPitchTrimCmd());   // Norm Elev Trim Tab Pos, --
 591    net->left_flap         = (float)(FCS->GetDfPos(ofNorm));    // Norm Flap Pos, --
 592    net->right_flap        = (float)(FCS->GetDfPos(ofNorm));    // Norm Flap Pos, --
 593    net->left_aileron      = (float)(FCS->GetDaLPos(ofNorm));   // Norm L Aileron Pos, --
 594    net->right_aileron     = (float)(FCS->GetDaRPos(ofNorm));   // Norm R Aileron Pos, --
 595    net->rudder            = (float)(FCS->GetDrPos(ofNorm));    // Norm Rudder Pos, --
 596    net->nose_wheel        = (float)(FCS->GetDrPos(ofNorm));    // *** FIX ***  Using Rudder Pos for NWS, --
 597    net->speedbrake        = (float)(FCS->GetDsbPos(ofNorm));   // Norm Speedbrake Pos, --
 598    net->spoilers          = (float)(FCS->GetDspPos(ofNorm));   // Norm Spoiler Pos, --
 599
 600
 601    // Convert the net buffer to network format
 602    if ( isLittleEndian ) {
 603        net->version = htonl(net->version);
 604
 605        htond(net->longitude);
 606        htond(net->latitude);
 607        htond(net->altitude);
 608        htonf(net->agl);
 609        htonf(net->phi);
 610        htonf(net->theta);
 611        htonf(net->psi);
 612        htonf(net->alpha);
 613        htonf(net->beta);
 614
 615        htonf(net->phidot);
 616        htonf(net->thetadot);
 617        htonf(net->psidot);
 618        htonf(net->vcas);
 619        htonf(net->climb_rate);
 620        htonf(net->v_north);
 621        htonf(net->v_east);
 622        htonf(net->v_down);
 623        htonf(net->v_wind_body_north);
 624        htonf(net->v_wind_body_east);
 625        htonf(net->v_wind_body_down);
 626
 627        htonf(net->A_X_pilot);
 628        htonf(net->A_Y_pilot);
 629        htonf(net->A_Z_pilot);
 630
 631        htonf(net->stall_warning);
 632        htonf(net->slip_deg);
 633
 634        for (i=0; i<net->num_engines; ++i ) {
 635            net->eng_state[i] = htonl(net->eng_state[i]);
 636            htonf(net->rpm[i]);
 637            htonf(net->fuel_flow[i]);
 638            htonf(net->fuel_px[i]);
 639            htonf(net->egt[i]);
 640            htonf(net->cht[i]);
 641            htonf(net->mp_osi[i]);
 642            htonf(net->tit[i]);
 643            htonf(net->oil_temp[i]);
 644            htonf(net->oil_px[i]);
 645        }
 646        net->num_engines = htonl(net->num_engines);
 647
 648        for (i=0; i<net->num_tanks; ++i ) {
 649            htonf(net->fuel_quantity[i]);
 650        }
 651        net->num_tanks = htonl(net->num_tanks);
 652
 653        for (i=0; i<net->num_wheels; ++i ) {
 654            net->wow[i] = htonl(net->wow[i]);
 655            htonf(net->gear_pos[i]);
 656            htonf(net->gear_steer[i]);
 657            htonf(net->gear_compression[i]);
 658        }
 659        net->num_wheels = htonl(net->num_wheels);
 660
 661        net->cur_time = htonl( net->cur_time );
 662        net->warp = htonl( net->warp );
 663        htonf(net->visibility);
 664
 665        htonf(net->elevator);
 666        htonf(net->elevator_trim_tab);
 667        htonf(net->left_flap);
 668        htonf(net->right_flap);
 669        htonf(net->left_aileron);
 670        htonf(net->right_aileron);
 671        htonf(net->rudder);
 672        htonf(net->nose_wheel);
 673        htonf(net->speedbrake);
 674        htonf(net->spoilers);
 675    }
 676}
 677
 678//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 679
 680void FGOutput::FlightGearSocketOutput(void)
 681{
 682  int length = sizeof(fgSockBuf);
 683
 684
 685  if (flightGearSocket == NULL) return;
 686  if (!flightGearSocket->GetConnectStatus()) return;
 687
 688  SocketDataFill(&fgSockBuf);
 689  flightGearSocket->Send((char *)&fgSockBuf, length);
 690}
 691
 692//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 693
 694void FGOutput::SocketOutput(void)
 695{
 696  string asciiData, scratch;
 697
 698  if (socket == NULL) return;
 699  if (!socket->GetConnectStatus()) return;
 700
 701  socket->Clear();
 702  if (sFirstPass) {
 703    socket->Clear("<LABELS>");
 704    socket->Append("Time");
 705
 706    if (SubSystems & ssAerosurfaces) {
 707      socket->Append("Aileron Command");
 708      socket->Append("Elevator Command");
 709      socket->Append("Rudder Command");
 710      socket->Append("Flap Command");
 711      socket->Append("Left Aileron Position");
 712      socket->Append("Right Aileron Position");
 713      socket->Append("Elevator Position");
 714      socket->Append("Rudder Position");
 715      socket->Append("Flap Position");
 716    }
 717
 718    if (SubSystems & ssRates) {
 719      socket->Append("P");
 720      socket->Append("Q");
 721      socket->Append("R");
 722      socket->Append("PDot");
 723      socket->Append("QDot");
 724      socket->Append("RDot");
 725    }
 726
 727    if (SubSystems & ssVelocities) {
 728      socket->Append("QBar");
 729      socket->Append("Vtotal");
 730      socket->Append("UBody");
 731      socket->Append("VBody");
 732      socket->Append("WBody");
 733      socket->Append("UAero");
 734      socket->Append("VAero");
 735      socket->Append("WAero");
 736      socket->Append("Vn");
 737      socket->Append("Ve");
 738      socket->Append("Vd");
 739    }
 740    if (SubSystems & ssForces) {
 741      socket->Append("F_Drag");
 742      socket->Append("F_Side");
 743      socket->Append("F_Lift");
 744      socket->Append("LoD");
 745      socket->Append("Fx");
 746      socket->Append("Fy");
 747      socket->Append("Fz");
 748    }
 749    if (SubSystems & ssMoments) {
 750      socket->Append("L");
 751      socket->Append("M");
 752      socket->Append("N");
 753    }
 754    if (SubSystems & ssAtmosphere) {
 755      socket->Append("Rho");
 756      socket->Append("SL pressure");
 757      socket->Append("Ambient pressure");
 758      socket->Append("Turbulence Magnitude");
 759      socket->Append("Turbulence Direction X");
 760      socket->Append("Turbulence Direction Y");
 761      socket->Append("Turbulence Direction Z");
 762      socket->Append("NWind");
 763      socket->Append("EWind");
 764      socket->Append("DWind");
 765    }
 766    if (SubSystems & ssMassProps) {
 767      socket->Append("Ixx");
 768      socket->Append("Ixy");
 769      socket->Append("Ixz");
 770      socket->Append("Iyx");
 771      socket->Append("Iyy");
 772      socket->Append("Iyz");
 773      socket->Append("Izx");
 774      socket->Append("Izy");
 775      socket->Append("Izz");
 776      socket->Append("Mass");
 777      socket->Append("Xcg");
 778      socket->Append("Ycg");
 779      socket->Append("Zcg");
 780    }
 781    if (SubSystems & ssPropagate) {
 782        socket->Append("Altitude");
 783        socket->Append("Phi (deg)");
 784        socket->Append("Tht (deg)");
 785        socket->Append("Psi (deg)");
 786        socket->Append("Alpha (deg)");
 787        socket->Append("Beta (deg)");
 788        socket->Append("Latitude (deg)");
 789        socket->Append("Longitude (deg)");
 790    }
 791    if (SubSystems & ssCoefficients) {
 792      scratch = Aerodynamics->GetCoefficientStrings(",");
 793      if (scratch.length() != 0) socket->Append(scratch);
 794    }
 795    if (SubSystems & ssFCS) {
 796      scratch = FCS->GetComponentStrings(",");
 797      if (scratch.length() != 0) socket->Append(scratch);
 798    }
 799    if (SubSystems & ssGroundReactions) {
 800      socket->Append(GroundReactions->GetGroundReactionStrings(","));
 801    }
 802    if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
 803      socket->Append(Propulsion->GetPropulsionStrings(","));
 804    }
 805    if (OutputProperties.size() > 0) {
 806      for (unsigned int i=0;i<OutputProperties.size();i++) {
 807        socket->Append(OutputProperties[i]->GetPrintableName());
 808      }
 809    }
 810
 811    sFirstPass = false;
 812    socket->Send();
 813  }
 814
 815  socket->Clear();
 816  socket->Append(State->Getsim_time());
 817
 818  if (SubSystems & ssAerosurfaces) {
 819    socket->Append(FCS->GetDaCmd());
 820    socket->Append(FCS->GetDeCmd());
 821    socket->Append(FCS->GetDrCmd());
 822    socket->Append(FCS->GetDfCmd());
 823    socket->Append(FCS->GetDaLPos());
 824    socket->Append(FCS->GetDaRPos());
 825    socket->Append(FCS->GetDePos());
 826    socket->Append(FCS->GetDrPos());
 827    socket->Append(FCS->GetDfPos());
 828  }
 829  if (SubSystems & ssRates) {
 830    socket->Append(radtodeg*Propagate->GetPQR(eP));
 831    socket->Append(radtodeg*Propagate->GetPQR(eQ));
 832    socket->Append(radtodeg*Propagate->GetPQR(eR));
 833    socket->Append(radtodeg*Propagate->GetPQRdot(eP));
 834    socket->Append(radtodeg*Propagate->GetPQRdot(eQ));
 835    socket->Append(radtodeg*Propagate->GetPQRdot(eR));
 836  }
 837  if (SubSystems & ssVelocities) {
 838    socket->Append(Auxiliary->Getqbar());
 839    socket->Append(Auxiliary->GetVt());
 840    socket->Append(Propagate->GetUVW(eU));
 841    socket->Append(Propagate->GetUVW(eV));
 842    socket->Append(Propagate->GetUVW(eW));
 843    socket->Append(Auxiliary->GetAeroUVW(eU));
 844    socket->Append(Auxiliary->GetAeroUVW(eV));
 845    socket->Append(Auxiliary->GetAeroUVW(eW));
 846    socket->Append(Propagate->GetVel(eNorth));
 847    socket->Append(Propagate->GetVel(eEast));
 848    socket->Append(Propagate->GetVel(eDown));
 849  }
 850  if (SubSystems & ssForces) {
 851    socket->Append(Aerodynamics->GetvFw()(eDrag));
 852    socket->Append(Aerodynamics->GetvFw()(eSide));
 853    socket->Append(Aerodynamics->GetvFw()(eLift));
 854    socket->Append(Aerodynamics->GetLoD());
 855    socket->Append(Aircraft->GetForces(eX));
 856    socket->Append(Aircraft->GetForces(eY));
 857    socket->Append(Aircraft->GetForces(eZ));
 858  }
 859  if (SubSystems & ssMoments) {
 860    socket->Append(Aircraft->GetMoments(eL));
 861    socket->Append(Aircraft->GetMoments(eM));
 862    socket->Append(Aircraft->GetMoments(eN));
 863  }
 864  if (SubSystems & ssAtmosphere) {
 865    socket->Append(Atmosphere->GetDensity());
 866    socket->Append(Atmosphere->GetPressureSL());
 867    socket->Append(Atmosphere->GetPressure());
 868    socket->Append(Atmosphere->GetTurbMagnitude());
 869    socket->Append(Atmosphere->GetTurbDirection().Dump(","));
 870    socket->Append(Atmosphere->GetTotalWindNED().Dump(","));
 871  }
 872  if (SubSystems & ssMassProps) {
 873    socket->Append(MassBalance->GetJ()(1,1));
 874    socket->Append(MassBalance->GetJ()(1,2));
 875    socket->Append(MassBalance->GetJ()(1,3));
 876    socket->Append(MassBalance->GetJ()(2,1));
 877    socket->Append(MassBalance->GetJ()(2,2));
 878    socket->Append(MassBalance->GetJ()(2,3));
 879    socket->Append(MassBalance->GetJ()(3,1));
 880    socket->Append(MassBalance->GetJ()(3,2));
 881    socket->Append(MassBalance->GetJ()(3,3));
 882    socket->Append(MassBalance->GetMass());
 883    socket->Append(MassBalance->GetXYZcg()(eX));
 884    socket->Append(MassBalance->GetXYZcg()(eY));
 885    socket->Append(MassBalance->GetXYZcg()(eZ));
 886  }
 887  if (SubSystems & ssPropagate) {
 888    socket->Append(Propagate->GetAltitudeASL());
 889    socket->Append(radtodeg*Propagate->GetEuler(ePhi));
 890    socket->Append(radtodeg*Propagate->GetEuler(eTht));
 891    socket->Append(radtodeg*Propagate->GetEuler(ePsi));
 892    socket->Append(Auxiliary->Getalpha(inDegrees));
 893    socket->Append(Auxiliary->Getbeta(inDegrees));
 894    socket->Append(Propagate->GetLocation().GetLatitudeDeg());
 895    socket->Append(Propagate->GetLocation().GetLongitudeDeg());
 896  }
 897  if (SubSystems & ssCoefficients) {
 898    scratch = Aerodynamics->GetCoefficientValues(",");
 899    if (scratch.length() != 0) socket->Append(scratch);
 900  }
 901  if (SubSystems & ssFCS) {
 902    scratch = FCS->GetComponentValues(",");
 903    if (scratch.length() != 0) socket->Append(scratch);
 904  }
 905  if (SubSystems & ssGroundReactions) {
 906    socket->Append(GroundReactions->GetGroundReactionValues(","));
 907  }
 908  if (SubSystems & ssPropulsion && Propulsion->GetNumEngines() > 0) {
 909    socket->Append(Propulsion->GetPropulsionValues(","));
 910  }
 911
 912  for (unsigned int i=0;i<OutputProperties.size();i++) {
 913    socket->Append(OutputProperties[i]->getDoubleValue());
 914  }
 915
 916  socket->Send();
 917}
 918
 919//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 920
 921void FGOutput::SocketStatusOutput(string out_str)
 922{
 923  string asciiData;
 924
 925  if (socket == NULL) return;
 926
 927  socket->Clear();
 928  asciiData = string("<STATUS>") + out_str;
 929  socket->Append(asciiData.c_str());
 930  socket->Send();
 931}
 932
 933//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 934
 935bool FGOutput::Load(Element* element)
 936{
 937  string type="", parameter="";
 938  string name="";
 939  string protocol="tcp";
 940  int OutRate = 0;
 941  string property;
 942  unsigned int port;
 943  Element *property_element;
 944
 945  string separator = "/";
 946
 947  if (!DirectivesFile.empty()) { // A directives filename from the command line overrides
 948    output_file_name = DirectivesFile;      // one found in the config file.
 949    document = LoadXMLDocument(output_file_name);
 950  } else if (!element->GetAttributeValue("file").empty()) {
 951    output_file_name = element->GetAttributeValue("file");
 952    document = LoadXMLDocument(output_file_name);
 953  } else {
 954    document = element;
 955  }
 956
 957  name = document->GetAttributeValue("name");
 958  type = document->GetAttributeValue("type");
 959  SetType(type);
 960  if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) {
 961    port = atoi(document->GetAttributeValue("port").c_str());
 962    socket = new FGfdmSocket(name, port);
 963  } else if (!document->GetAttributeValue("port").empty() && type == string("FLIGHTGEAR")) {
 964    port = atoi(document->GetAttributeValue("port").c_str());
 965    if (!document->GetAttributeValue("protocol").empty())
 966       protocol = document->GetAttributeValue("protocol");
 967    if (protocol == "udp")
 968       flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptUDP);  // create udp socket
 969    else
 970       flightGearSocket = new FGfdmSocket(name, port, FGfdmSocket::ptTCP);  // create tcp socket (default)
 971  } else {
 972    BaseFilename = Filename = name;
 973  }
 974  if (!document->GetAttributeValue("rate").empty()) {
 975    OutRate = (int)document->GetAttributeValueAsNumber("rate");
 976  } else {
 977    OutRate = 1;
 978  }
 979
 980  if (document->FindElementValue("simulation") == string("ON"))
 981    SubSystems += ssSimulation;
 982  if (document->FindElementValue("aerosurfaces") == string("ON"))
 983    SubSystems += ssAerosurfaces;
 984  if (document->FindElementValue("rates") == string("ON"))
 985    SubSystems += ssRates;
 986  if (document->FindElementValue("velocities") == string("ON"))
 987    SubSystems += ssVelocities;
 988  if (document->FindElementValue("forces") == string("ON"))
 989    SubSystems += ssForces;
 990  if (document->FindElementValue("moments") == string("ON"))
 991    SubSystems += ssMoments;
 992  if (document->FindElementValue("atmosphere") == string("ON"))
 993    SubSystems += ssAtmosphere;
 994  if (document->FindElementValue("massprops") == string("ON"))
 995    SubSystems += ssMassProps;
 996  if (document->FindElementValue("position") == string("ON"))
 997    SubSystems += ssPropagate;
 998  if (document->FindElementValue("coefficients") == string("ON"))
 999    SubSystems += ssCoefficients;
1000  if (document->FindElementValue("ground_reactions") == string("ON"))
1001    SubSystems += ssGroundReactions;
1002  if (document->FindElementValue("fcs") == string("ON"))
1003    SubSystems += ssFCS;
1004  if (document->FindElementValue("propulsion") == string("ON"))
1005    SubSystems += ssPropulsion;
1006  property_element = document->FindElement("property");
1007  while (property_element) {
1008    string property_str = property_element->GetDataLine();
1009    FGPropertyManager* node = PropertyManager->GetNode(property_str);
1010    if (!node) {
1011      cerr << fgred << highint << endl << "  No property by the name "
1012           << property_str << " has been defined. This property will " << endl
1013           << "  not be logged. You should check your configuration file."
1014           << reset << endl;
1015    } else {
1016      OutputProperties.push_back(node);
1017    }
1018    property_element = document->FindNextElement("property");
1019  }
1020
1021  SetRate(OutRate);
1022
1023  Debug(2);
1024
1025  return true;
1026}
1027
1028//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029
1030void FGOutput::SetRate(int rtHz)
1031{
1032  rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz);
1033  if (rtHz > 0) {
1034    rate = (int)(0.5 + 1.0/(State->Getdt()*rtHz));
1035    Enable();
1036  } else {
1037    rate = 1;
1038    Disable();
1039  }
1040}
1041
1042//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043//    The bitmasked value choices are as follows:
1044//    unset: In this case (the default) JSBSim would only print
1045//       out the normally expected messages, essentially echoing
1046//       the config files as they are read. If the environment
1047//       variable is not set, debug_lvl is set to 1 internally
1048//    0: This requests JSBSim not to output any messages
1049//       whatsoever.
1050//    1: This value explicity requests the normal JSBSim
1051//       startup messages
1052//    2: This value asks for a message to be printed out when
1053//       a class is instantiated
1054//    4: When this value is set, a message is displayed when a
1055//       FGModel object executes its Run() method
1056//    8: When this value is set, various runtime state variables
1057//       are printed out periodically
1058//    16: When set various parameters are sanity checked and
1059//       a message is printed out when they go out of bounds
1060
1061void FGOutput::Debug(int from)
1062{
1063  string scratch="";
1064
1065  if (debug_lvl <= 0) return;
1066
1067  if (debug_lvl & 1) { // Standard console startup message output
1068    if (from == 0) { // Constructor
1069
1070    }
1071    if (from == 2) {
1072      if (output_file_name.empty())
1073        cout << "  " << "Output parameters read inline" << endl;
1074      else
1075        cout << "    Output parameters read from file: " << output_file_name << endl;
1076
1077      if (Filename == "cout" || Filename == "COUT") {
1078        scratch = "    Log output goes to screen console";
1079      } else if (!Filename.empty()) {
1080        scratch = "    Log output goes to file: " + Filename;
1081      }
1082      switch (Type) {
1083      case otCSV:
1084        cout << scratch << " in CSV format output at rate " << 1/(State->Getdt()*rate) << " Hz" << endl;
1085        break;
1086      case otNone:
1087        cout << "  No log output" << endl;
1088        break;
1089      }
1090
1091      if (SubSystems & ssSimulation)      cout << "    Simulation parameters logged" << endl;
1092      if (SubSystems & ssAerosurfaces)    cout << "    Aerosurface parameters logged" << endl;
1093      if (SubSystems & ssRates)           cout << "    Rate parameters logged" << endl;
1094      if (SubSystems & ssVelocities)      cout << "    Velocity parameters logged" << endl;
1095      if (SubSystems & ssForces)          cout << "    Force parameters logged" << endl;
1096      if (SubSystems & ssMoments)         cout << "    Moments parameters logged" << endl;
1097      if (SubSystems & ssAtmosphere)      cout << "    Atmosphere parameters logged" << endl;
1098      if (SubSystems & ssMassProps)       cout << "    Mass parameters logged" << endl;
1099      if (SubSystems & ssCoefficients)    cout << "    Coefficient parameters logged" << endl;
1100      if (SubSystems & ssPropagate)       cout << "    Propagate parameters logged" << endl;
1101      if (SubSystems & ssGroundReactions) cout << "    Ground parameters logged" << endl;
1102      if (SubSystems & ssFCS)             cout << "    FCS parameters logged" << endl;
1103      if (SubSystems & ssPropulsion)      cout << "    Propulsion parameters logged" << endl;
1104      if (OutputProperties.size() > 0)    cout << "    Properties logged:" << endl;
1105      for (unsigned int i=0;i<OutputProperties.size();i++) {
1106        cout << "      - " << OutputProperties[i]->GetName() << endl;
1107      }
1108    }
1109  }
1110  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
1111    if (from == 0) cout << "Instantiated: FGOutput" << endl;
1112    if (from == 1) cout << "Destroyed:    FGOutput" << endl;
1113  }
1114  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
1115  }
1116  if (debug_lvl & 8 ) { // Runtime state variables
1117  }
1118  if (debug_lvl & 16) { // Sanity checking
1119  }
1120  if (debug_lvl & 64) {
1121    if (from == 0) { // Constructor
1122      cout << IdSrc << endl;
1123      cout << IdHdr << endl;
1124    }
1125  }
1126}
1127}