44#include "FGOutputFG.h"
45#include "FGXMLElement.h"
46#include "models/FGAuxiliary.h"
47#include "models/FGPropulsion.h"
48#include "models/FGFCS.h"
49#include "models/propulsion/FGPiston.h"
50#include "models/propulsion/FGElectric.h"
51#include "models/propulsion/FGTank.h"
54#if defined(WIN32) && !defined(__CYGWIN__)
57# include <netinet/in.h>
61# define min(X,Y) X<Y?X:Y
64static const int endianTest = 1;
65#define isLittleEndian (*((char *) &endianTest ) != 0)
81static void htond (
double &x)
83 if ( isLittleEndian ) {
87 Double_Overlay = (
int *) &x;
88 Holding_Buffer = Double_Overlay [0];
90 Double_Overlay [0] = htonl (Double_Overlay [1]);
91 Double_Overlay [1] = htonl (Holding_Buffer);
98static void htonf (
float &x)
100 if ( isLittleEndian ) {
104 Float_Overlay = (
int *) &x;
105 Holding_Buffer = Float_Overlay [0];
107 Float_Overlay [0] = htonl (Holding_Buffer);
121 memset(&fgSockBuf, 0x0,
sizeof(fgSockBuf));
126 if (Propulsion->GetNumEngines() > FGNetFDM::FG_MAX_ENGINES)
127 log <<
"This vehicle has " << Propulsion->GetNumEngines() <<
" engines, but the current \n"
128 <<
"version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_ENGINES <<
" engines.\n"
129 <<
"Only the first " << FGNetFDM::FG_MAX_ENGINES <<
" engines will be used.\n";
132 if (Propulsion->GetNumTanks() > FGNetFDM::FG_MAX_TANKS)
133 log <<
"This vehicle has " << Propulsion->GetNumTanks() <<
" tanks, but the current \n"
134 <<
"version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_TANKS <<
" tanks.\n"
135 <<
"Only the first " << FGNetFDM::FG_MAX_TANKS <<
" tanks will be used.\n";
138 if (GroundReactions->GetNumGearUnits() > FGNetFDM::FG_MAX_WHEELS)
139 log <<
"This vehicle has " << GroundReactions->GetNumGearUnits() <<
" bogeys, but the current \n"
140 <<
"version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_WHEELS <<
" bogeys.\n"
141 <<
"Only the first " << FGNetFDM::FG_MAX_WHEELS <<
" bogeys will be used.\n";
158 outputOptions.useSimTime =
true;
176void FGOutputFG::SocketDataFill(FGNetFDM* net)
181 net->version = FG_NET_FDM_VERSION;
184 net->longitude = Propagate->GetLongitude();
185 net->latitude = Propagate->GetGeodLatitudeRad();
186 net->altitude = Propagate->GetAltitudeASL()*0.3048;
187 net->agl = (float)(Propagate->GetDistanceAGL()*0.3048);
189 net->phi = (float)(Propagate->GetEuler(ePhi));
190 net->theta = (float)(Propagate->GetEuler(eTht));
191 net->psi = (float)(Propagate->GetEuler(ePsi));
193 net->alpha = (float)(Auxiliary->Getalpha());
194 net->beta = (float)(Auxiliary->Getbeta());
197 net->phidot = (float)(Auxiliary->GetEulerRates(ePhi));
198 net->thetadot = (float)(Auxiliary->GetEulerRates(eTht));
199 net->psidot = (float)(Auxiliary->GetEulerRates(ePsi));
200 net->vcas = (float)(Auxiliary->GetVcalibratedKTS());
201 net->climb_rate = (float)(Propagate->Gethdot());
202 net->v_north = (float)(Propagate->GetVel(eNorth));
203 net->v_east = (float)(Propagate->GetVel(eEast));
204 net->v_down = (float)(Propagate->GetVel(eDown));
206 net->v_body_u = (float)(Propagate->GetUVW(1));
207 net->v_body_v = (float)(Propagate->GetUVW(2));
208 net->v_body_w = (float)(Propagate->GetUVW(3));
211 net->A_X_pilot = (float)(Auxiliary->GetPilotAccel(1));
212 net->A_Y_pilot = (float)(Auxiliary->GetPilotAccel(2));
213 net->A_Z_pilot = (float)(Auxiliary->GetPilotAccel(3));
216 net->stall_warning = 0.0;
217 net->slip_deg = (float)(Auxiliary->Getbeta(inDegrees));
219 net->num_engines = min(FGNetFDM::FG_MAX_ENGINES,Propulsion->GetNumEngines());
221 for (i=0; i<net->num_engines; i++) {
222 auto engine = Propulsion->GetEngine(i);
223 if (engine->GetRunning())
224 net->eng_state[i] = 2;
225 else if (engine->GetCranking())
226 net->eng_state[i] = 1;
228 net->eng_state[i] = 0;
230 switch (engine->GetType()) {
231 case (FGEngine::etRocket):
233 case (FGEngine::etPiston):
235 auto piston_engine = static_pointer_cast<FGPiston>(engine);
236 net->rpm[i] = (float)(piston_engine->getRPM());
237 net->fuel_flow[i] = (float)(piston_engine->getFuelFlow_gph());
239 net->egt[i] = (float)(piston_engine->GetEGT());
240 net->cht[i] = (float)(piston_engine->getCylinderHeadTemp_degF());
241 net->mp_osi[i] = (float)(piston_engine->getManifoldPressure_inHg());
242 net->oil_temp[i] = (float)(piston_engine->getOilTemp_degF());
243 net->oil_px[i] = (float)(piston_engine->getOilPressure_psi());
247 case (FGEngine::etTurbine):
249 case (FGEngine::etTurboprop):
251 case (FGEngine::etElectric):
252 net->rpm[i] =
static_cast<float>(static_pointer_cast<FGElectric>(engine)->getRPM());
254 case (FGEngine::etUnknown):
259 net->num_tanks = min(FGNetFDM::FG_MAX_TANKS, Propulsion->GetNumTanks());
261 for (i=0; i<net->num_tanks; i++) {
262 net->fuel_quantity[i] =
static_cast<float>(Propulsion->GetTank(i)->GetContents());
265 net->num_wheels = min(FGNetFDM::FG_MAX_WHEELS, GroundReactions->GetNumGearUnits());
267 for (i=0; i<net->num_wheels; i++) {
268 net->wow[i] = GroundReactions->GetGearUnit(i)->GetWOW();
269 if (GroundReactions->GetGearUnit(i)->GetGearUnitDown())
270 net->gear_pos[i] = 1;
272 net->gear_pos[i] = 0;
273 net->gear_steer[i] = (float)(GroundReactions->GetGearUnit(i)->GetSteerNorm());
274 net->gear_compression[i] = (float)(GroundReactions->GetGearUnit(i)->GetCompLen());
278 if (outputOptions.useSimTime) {
280 net->cur_time =
static_cast<uint32_t
>(FDMExec->
GetSimTime()*outputOptions.timeFactor);
283 net->cur_time = 1234567890u;
287 net->visibility = 25000.0;
290 net->elevator = (float)(FCS->GetDePos(ofNorm));
291 net->elevator_trim_tab = (float)(FCS->GetPitchTrimCmd());
292 net->left_flap = (float)(FCS->GetDfPos(ofNorm));
293 net->right_flap = (float)(FCS->GetDfPos(ofNorm));
294 net->left_aileron = (float)(FCS->GetDaLPos(ofNorm));
295 net->right_aileron = (float)(FCS->GetDaRPos(ofNorm));
296 net->rudder = (float)(FCS->GetDrPos(ofNorm));
297 net->nose_wheel = (float)(FCS->GetDrPos(ofNorm));
298 net->speedbrake = (float)(FCS->GetDsbPos(ofNorm));
299 net->spoilers = (float)(FCS->GetDspPos(ofNorm));
302 if ( isLittleEndian ) {
303 net->version = htonl(net->version);
305 htond(net->longitude);
306 htond(net->latitude);
307 htond(net->altitude);
316 htonf(net->thetadot);
319 htonf(net->climb_rate);
323 htonf(net->v_body_u);
324 htonf(net->v_body_v);
325 htonf(net->v_body_w);
327 htonf(net->A_X_pilot);
328 htonf(net->A_Y_pilot);
329 htonf(net->A_Z_pilot);
331 htonf(net->stall_warning);
332 htonf(net->slip_deg);
334 for (i=0; i<net->num_engines; ++i ) {
335 net->eng_state[i] = htonl(net->eng_state[i]);
337 htonf(net->fuel_flow[i]);
338 htonf(net->fuel_px[i]);
341 htonf(net->mp_osi[i]);
343 htonf(net->oil_temp[i]);
344 htonf(net->oil_px[i]);
346 net->num_engines = htonl(net->num_engines);
348 for (i=0; i<net->num_tanks; ++i ) {
349 htonf(net->fuel_quantity[i]);
351 net->num_tanks = htonl(net->num_tanks);
353 for (i=0; i<net->num_wheels; ++i ) {
354 net->wow[i] = htonl(net->wow[i]);
355 htonf(net->gear_pos[i]);
356 htonf(net->gear_steer[i]);
357 htonf(net->gear_compression[i]);
359 net->num_wheels = htonl(net->num_wheels);
361 net->cur_time = htonl( net->cur_time );
362 net->warp = htonl( net->warp );
363 htonf(net->visibility);
365 htonf(net->elevator);
366 htonf(net->elevator_trim_tab);
367 htonf(net->left_flap);
368 htonf(net->right_flap);
369 htonf(net->left_aileron);
370 htonf(net->right_aileron);
372 htonf(net->nose_wheel);
373 htonf(net->speedbrake);
374 htonf(net->spoilers);
382 int length =
sizeof(fgSockBuf);
384 if (socket == 0)
return;
387 SocketDataFill(&fgSockBuf);
388 socket->
Send((
char *)&fgSockBuf, length);
Element * FindElement(const std::string &el="")
Searches for a specified element.
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
Encapsulates the JSBSim simulation executive.
int GetDebugLevel(void) const
Retrieves the current debug level setting.
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
FGOutputFG(FGFDMExec *fdmex)
Constructor.
void Print(void) override
Generate the output.
bool Load(Element *) override
Evaluate the output directives from an XML file.
Implements the output to a socket.
bool Load(Element *el) override
Init the output directives from an XML file.
bool GetConnectStatus(void)
Return the connection status of the socket.
void Send(void)
Send the internal buffer over the socket connection.
Main namespace for the JSBSim Flight Dynamics Model.