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"
53#if defined(WIN32) && !defined(__CYGWIN__)
56# include <netinet/in.h>
60# define min(X,Y) X<Y?X:Y
63static const int endianTest = 1;
64#define isLittleEndian (*((char *) &endianTest ) != 0)
80static void htond (
double &x)
82 if ( isLittleEndian ) {
86 Double_Overlay = (
int *) &x;
87 Holding_Buffer = Double_Overlay [0];
89 Double_Overlay [0] = htonl (Double_Overlay [1]);
90 Double_Overlay [1] = htonl (Holding_Buffer);
97static void htonf (
float &x)
99 if ( isLittleEndian ) {
103 Float_Overlay = (
int *) &x;
104 Holding_Buffer = Float_Overlay [0];
106 Float_Overlay [0] = htonl (Holding_Buffer);
120 memset(&fgSockBuf, 0x0,
sizeof(fgSockBuf));
124 if (Propulsion->GetNumEngines() > FGNetFDM::FG_MAX_ENGINES)
125 cerr <<
"This vehicle has " << Propulsion->GetNumEngines() <<
" engines, but the current " << endl
126 <<
"version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_ENGINES <<
" engines." << endl
127 <<
"Only the first " << FGNetFDM::FG_MAX_ENGINES <<
" engines will be used." << endl;
130 if (Propulsion->GetNumTanks() > FGNetFDM::FG_MAX_TANKS)
131 cerr <<
"This vehicle has " << Propulsion->GetNumTanks() <<
" tanks, but the current " << endl
132 <<
"version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_TANKS <<
" tanks." << endl
133 <<
"Only the first " << FGNetFDM::FG_MAX_TANKS <<
" tanks will be used." << endl;
136 if (GroundReactions->GetNumGearUnits() > FGNetFDM::FG_MAX_WHEELS)
137 cerr <<
"This vehicle has " << GroundReactions->GetNumGearUnits() <<
" bogeys, but the current " << endl
138 <<
"version of FlightGear's FGNetFDM only supports " << FGNetFDM::FG_MAX_WHEELS <<
" bogeys." << endl
139 <<
"Only the first " << FGNetFDM::FG_MAX_WHEELS <<
" bogeys will be used." << endl;
156 outputOptions.useSimTime =
true;
174void FGOutputFG::SocketDataFill(FGNetFDM* net)
179 net->version = FG_NET_FDM_VERSION;
182 net->longitude = Propagate->GetLongitude();
183 net->latitude = Propagate->GetGeodLatitudeRad();
184 net->altitude = Propagate->GetAltitudeASL()*0.3048;
185 net->agl = (float)(Propagate->GetDistanceAGL()*0.3048);
187 net->phi = (float)(Propagate->GetEuler(ePhi));
188 net->theta = (float)(Propagate->GetEuler(eTht));
189 net->psi = (float)(Propagate->GetEuler(ePsi));
191 net->alpha = (float)(Auxiliary->Getalpha());
192 net->beta = (float)(Auxiliary->Getbeta());
195 net->phidot = (float)(Auxiliary->GetEulerRates(ePhi));
196 net->thetadot = (float)(Auxiliary->GetEulerRates(eTht));
197 net->psidot = (float)(Auxiliary->GetEulerRates(ePsi));
198 net->vcas = (float)(Auxiliary->GetVcalibratedKTS());
199 net->climb_rate = (float)(Propagate->Gethdot());
200 net->v_north = (float)(Propagate->GetVel(eNorth));
201 net->v_east = (float)(Propagate->GetVel(eEast));
202 net->v_down = (float)(Propagate->GetVel(eDown));
204 net->v_body_u = (float)(Propagate->GetUVW(1));
205 net->v_body_v = (float)(Propagate->GetUVW(2));
206 net->v_body_w = (float)(Propagate->GetUVW(3));
209 net->A_X_pilot = (float)(Auxiliary->GetPilotAccel(1));
210 net->A_Y_pilot = (float)(Auxiliary->GetPilotAccel(2));
211 net->A_Z_pilot = (float)(Auxiliary->GetPilotAccel(3));
214 net->stall_warning = 0.0;
215 net->slip_deg = (float)(Auxiliary->Getbeta(inDegrees));
217 net->num_engines = min(FGNetFDM::FG_MAX_ENGINES,Propulsion->GetNumEngines());
219 for (i=0; i<net->num_engines; i++) {
220 auto engine = Propulsion->GetEngine(i);
221 if (engine->GetRunning())
222 net->eng_state[i] = 2;
223 else if (engine->GetCranking())
224 net->eng_state[i] = 1;
226 net->eng_state[i] = 0;
228 switch (engine->GetType()) {
229 case (FGEngine::etRocket):
231 case (FGEngine::etPiston):
233 auto piston_engine = static_pointer_cast<FGPiston>(engine);
234 net->rpm[i] = (float)(piston_engine->getRPM());
235 net->fuel_flow[i] = (float)(piston_engine->getFuelFlow_gph());
237 net->egt[i] = (float)(piston_engine->GetEGT());
238 net->cht[i] = (float)(piston_engine->getCylinderHeadTemp_degF());
239 net->mp_osi[i] = (float)(piston_engine->getManifoldPressure_inHg());
240 net->oil_temp[i] = (float)(piston_engine->getOilTemp_degF());
241 net->oil_px[i] = (float)(piston_engine->getOilPressure_psi());
245 case (FGEngine::etTurbine):
247 case (FGEngine::etTurboprop):
249 case (FGEngine::etElectric):
250 net->rpm[i] =
static_cast<float>(static_pointer_cast<FGElectric>(engine)->getRPM());
252 case (FGEngine::etUnknown):
257 net->num_tanks = min(FGNetFDM::FG_MAX_TANKS, Propulsion->GetNumTanks());
259 for (i=0; i<net->num_tanks; i++) {
260 net->fuel_quantity[i] =
static_cast<float>(Propulsion->GetTank(i)->GetContents());
263 net->num_wheels = min(FGNetFDM::FG_MAX_WHEELS, GroundReactions->GetNumGearUnits());
265 for (i=0; i<net->num_wheels; i++) {
266 net->wow[i] = GroundReactions->GetGearUnit(i)->GetWOW();
267 if (GroundReactions->GetGearUnit(i)->GetGearUnitDown())
268 net->gear_pos[i] = 1;
270 net->gear_pos[i] = 0;
271 net->gear_steer[i] = (float)(GroundReactions->GetGearUnit(i)->GetSteerNorm());
272 net->gear_compression[i] = (float)(GroundReactions->GetGearUnit(i)->GetCompLen());
276 if (outputOptions.useSimTime) {
278 net->cur_time =
static_cast<uint32_t
>(FDMExec->
GetSimTime()*outputOptions.timeFactor);
281 net->cur_time = 1234567890u;
285 net->visibility = 25000.0;
288 net->elevator = (float)(FCS->GetDePos(ofNorm));
289 net->elevator_trim_tab = (float)(FCS->GetPitchTrimCmd());
290 net->left_flap = (float)(FCS->GetDfPos(ofNorm));
291 net->right_flap = (float)(FCS->GetDfPos(ofNorm));
292 net->left_aileron = (float)(FCS->GetDaLPos(ofNorm));
293 net->right_aileron = (float)(FCS->GetDaRPos(ofNorm));
294 net->rudder = (float)(FCS->GetDrPos(ofNorm));
295 net->nose_wheel = (float)(FCS->GetDrPos(ofNorm));
296 net->speedbrake = (float)(FCS->GetDsbPos(ofNorm));
297 net->spoilers = (float)(FCS->GetDspPos(ofNorm));
300 if ( isLittleEndian ) {
301 net->version = htonl(net->version);
303 htond(net->longitude);
304 htond(net->latitude);
305 htond(net->altitude);
314 htonf(net->thetadot);
317 htonf(net->climb_rate);
321 htonf(net->v_body_u);
322 htonf(net->v_body_v);
323 htonf(net->v_body_w);
325 htonf(net->A_X_pilot);
326 htonf(net->A_Y_pilot);
327 htonf(net->A_Z_pilot);
329 htonf(net->stall_warning);
330 htonf(net->slip_deg);
332 for (i=0; i<net->num_engines; ++i ) {
333 net->eng_state[i] = htonl(net->eng_state[i]);
335 htonf(net->fuel_flow[i]);
336 htonf(net->fuel_px[i]);
339 htonf(net->mp_osi[i]);
341 htonf(net->oil_temp[i]);
342 htonf(net->oil_px[i]);
344 net->num_engines = htonl(net->num_engines);
346 for (i=0; i<net->num_tanks; ++i ) {
347 htonf(net->fuel_quantity[i]);
349 net->num_tanks = htonl(net->num_tanks);
351 for (i=0; i<net->num_wheels; ++i ) {
352 net->wow[i] = htonl(net->wow[i]);
353 htonf(net->gear_pos[i]);
354 htonf(net->gear_steer[i]);
355 htonf(net->gear_compression[i]);
357 net->num_wheels = htonl(net->num_wheels);
359 net->cur_time = htonl( net->cur_time );
360 net->warp = htonl( net->warp );
361 htonf(net->visibility);
363 htonf(net->elevator);
364 htonf(net->elevator_trim_tab);
365 htonf(net->left_flap);
366 htonf(net->right_flap);
367 htonf(net->left_aileron);
368 htonf(net->right_aileron);
370 htonf(net->nose_wheel);
371 htonf(net->speedbrake);
372 htonf(net->spoilers);
380 int length =
sizeof(fgSockBuf);
382 if (socket == 0)
return;
385 SocketDataFill(&fgSockBuf);
386 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.