PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

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