Updates from "Jonathan Polley" <jwpolley@home.com> to convert from/to 'net'
format before reading/writing data from/to remote machine. This allows different endian machines to talk to each other. Also added support for passing time and time offset (warp) in the data packet.
This commit is contained in:
parent
4453bec3de
commit
847b968816
3 changed files with 106 additions and 36 deletions
|
@ -21,14 +21,45 @@
|
|||
// $Id$
|
||||
|
||||
|
||||
#include <netinet/in.h> // htonl() ntohl()
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/io/lowlevel.hxx> // endian tests
|
||||
#include <simgear/io/iochannel.hxx>
|
||||
|
||||
#include <FDM/flight.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
#include "native_fdm.hxx"
|
||||
|
||||
|
||||
|
||||
// The function htond is defined this way due to the way some
|
||||
// processors and OSes treat floating point values. Some will raise
|
||||
// an exception whenever a "bad" floating point value is loaded into a
|
||||
// floating point register. Solaris is notorious for this, but then
|
||||
// so is LynxOS on the PowerPC. By translating the data in place,
|
||||
// there is no need to load a FP register with the "corruped" floating
|
||||
// point value. By doing the BIG_ENDIAN test, I can optimize the
|
||||
// routine for big-endian processors so it can be as efficient as
|
||||
// possible
|
||||
static void htond (double &x)
|
||||
{
|
||||
if ( sgIsLittleEndian() ) {
|
||||
int *Double_Overlay;
|
||||
int Holding_Buffer;
|
||||
|
||||
Double_Overlay = (int *) &x;
|
||||
Holding_Buffer = Double_Overlay [0];
|
||||
|
||||
Double_Overlay [0] = htonl (Double_Overlay [1]);
|
||||
Double_Overlay [1] = htonl (Holding_Buffer);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FGNativeFDM::FGNativeFDM() {
|
||||
}
|
||||
|
||||
|
@ -58,40 +89,73 @@ bool FGNativeFDM::open() {
|
|||
}
|
||||
|
||||
|
||||
static void global2raw( const FGInterface *global, FGRawFDM *raw ) {
|
||||
raw->version = FG_RAW_FDM_VERSION;
|
||||
static void global2net( const FGInterface *global, FGNetFDM *net ) {
|
||||
net->version = FG_NET_FDM_VERSION;
|
||||
|
||||
// positions
|
||||
raw->longitude = cur_fdm_state->get_Longitude();
|
||||
raw->latitude = cur_fdm_state->get_Latitude();
|
||||
raw->altitude = cur_fdm_state->get_Altitude() * SG_FEET_TO_METER;
|
||||
raw->phi = cur_fdm_state->get_Phi();
|
||||
raw->theta = cur_fdm_state->get_Theta();
|
||||
raw->psi = cur_fdm_state->get_Psi();
|
||||
net->longitude = cur_fdm_state->get_Longitude();
|
||||
net->latitude = cur_fdm_state->get_Latitude();
|
||||
net->altitude = cur_fdm_state->get_Altitude() * SG_FEET_TO_METER;
|
||||
net->phi = cur_fdm_state->get_Phi();
|
||||
net->theta = cur_fdm_state->get_Theta();
|
||||
net->psi = cur_fdm_state->get_Psi();
|
||||
|
||||
// velocities
|
||||
raw->vcas = cur_fdm_state->get_V_calibrated_kts();
|
||||
raw->climb_rate = cur_fdm_state->get_Climb_Rate();
|
||||
net->vcas = cur_fdm_state->get_V_calibrated_kts();
|
||||
net->climb_rate = cur_fdm_state->get_Climb_Rate();
|
||||
|
||||
// time
|
||||
net->cur_time = globals->get_time_params()->get_cur_time();
|
||||
net->warp = globals->get_warp();
|
||||
|
||||
// Convert the net buffer to network format
|
||||
net->version = htonl(net->version);
|
||||
htond(net->longitude);
|
||||
htond(net->latitude);
|
||||
htond(net->altitude);
|
||||
htond(net->phi);
|
||||
htond(net->theta);
|
||||
htond(net->psi);
|
||||
htond(net->vcas);
|
||||
htond(net->climb_rate);
|
||||
net->cur_time = htonl( net->cur_time );
|
||||
net->warp = htonl( net->warp );
|
||||
}
|
||||
|
||||
|
||||
static void raw2global( const FGRawFDM *raw, FGInterface *global ) {
|
||||
if ( raw->version == FG_RAW_FDM_VERSION ) {
|
||||
// cout << "pos = " << raw->longitude << " " << raw->latitude << endl;
|
||||
static void net2global( FGNetFDM *net, FGInterface *global ) {
|
||||
|
||||
// Convert to the net buffer from network format
|
||||
net->version = htonl(net->version);
|
||||
htond(net->longitude);
|
||||
htond(net->latitude);
|
||||
htond(net->altitude);
|
||||
htond(net->phi);
|
||||
htond(net->theta);
|
||||
htond(net->psi);
|
||||
htond(net->vcas);
|
||||
htond(net->climb_rate);
|
||||
net->cur_time = htonl(net->cur_time);
|
||||
net->warp = htonl(net->warp);
|
||||
|
||||
if ( net->version == FG_NET_FDM_VERSION ) {
|
||||
// cout << "pos = " << net->longitude << " " << net->latitude << endl;
|
||||
// cout << "sea level rad = " << cur_fdm_state->get_Sea_level_radius() << endl;
|
||||
cur_fdm_state->_updateGeodeticPosition( raw->latitude,
|
||||
raw->longitude,
|
||||
raw->altitude
|
||||
cur_fdm_state->_updateGeodeticPosition( net->latitude,
|
||||
net->longitude,
|
||||
net->altitude
|
||||
* SG_METER_TO_FEET );
|
||||
cur_fdm_state->_set_Euler_Angles( raw->phi,
|
||||
raw->theta,
|
||||
raw->psi );
|
||||
cur_fdm_state->_set_V_calibrated_kts( raw->vcas );
|
||||
cur_fdm_state->_set_Climb_Rate( raw->climb_rate );
|
||||
cur_fdm_state->_set_Euler_Angles( net->phi,
|
||||
net->theta,
|
||||
net->psi );
|
||||
cur_fdm_state->_set_V_calibrated_kts( net->vcas );
|
||||
cur_fdm_state->_set_Climb_Rate( net->climb_rate );
|
||||
|
||||
globals->set_warp( net->warp );
|
||||
} else {
|
||||
SG_LOG( SG_IO, SG_ALERT, "Error: version mismatch in raw2global()" );
|
||||
SG_LOG( SG_IO, SG_ALERT, "Error: version mismatch in net2global()" );
|
||||
SG_LOG( SG_IO, SG_ALERT,
|
||||
"\tsomeone needs to upgrade raw_fdm.hxx and recompile." );
|
||||
"\tsomeone needs to upgrade net_fdm.hxx and recompile." );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +167,7 @@ bool FGNativeFDM::process() {
|
|||
|
||||
if ( get_direction() == SG_IO_OUT ) {
|
||||
// cout << "size of cur_fdm_state = " << length << endl;
|
||||
global2raw( cur_fdm_state, &buf );
|
||||
global2net( cur_fdm_state, &buf );
|
||||
if ( ! io->write( (char *)(& buf), length ) ) {
|
||||
SG_LOG( SG_IO, SG_ALERT, "Error writing data." );
|
||||
return false;
|
||||
|
@ -112,12 +176,12 @@ bool FGNativeFDM::process() {
|
|||
if ( io->get_type() == sgFileType ) {
|
||||
if ( io->read( (char *)(& buf), length ) == length ) {
|
||||
SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
|
||||
raw2global( &buf, cur_fdm_state );
|
||||
net2global( &buf, cur_fdm_state );
|
||||
}
|
||||
} else {
|
||||
while ( io->read( (char *)(& buf), length ) == length ) {
|
||||
SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
|
||||
raw2global( &buf, cur_fdm_state );
|
||||
net2global( &buf, cur_fdm_state );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
#include <FDM/flight.hxx>
|
||||
|
||||
#include "protocol.hxx"
|
||||
#include "raw_fdm.hxx"
|
||||
#include "net_fdm.hxx"
|
||||
|
||||
|
||||
class FGNativeFDM : public FGProtocol, public FGInterface {
|
||||
|
||||
FGRawFDM buf;
|
||||
FGNetFDM buf;
|
||||
int length;
|
||||
|
||||
public:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// raw_fdm.hxx -- defines a common raw I/O interface to the flight
|
||||
// net_fdm.hxx -- defines a common net I/O interface to the flight
|
||||
// dynamics model
|
||||
//
|
||||
// Written by Curtis Olson, started September 2001.
|
||||
|
@ -22,24 +22,28 @@
|
|||
// $Id$
|
||||
|
||||
|
||||
#ifndef _RAW_FDM_HXX
|
||||
#define _RAW_FDM_HXX
|
||||
#ifndef _NET_FDM_HXX
|
||||
#define _NET_FDM_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
const int FG_RAW_FDM_VERSION = 3;
|
||||
const int FG_NET_FDM_VERSION = 0x0104;
|
||||
|
||||
// Define a structure containing the top level flight dynamics model
|
||||
// parameters
|
||||
|
||||
class FGRawFDM {
|
||||
class FGNetFDM {
|
||||
|
||||
public:
|
||||
|
||||
int version; // increment when data values change
|
||||
int pad; // keep doubles 64-bit aligned for some
|
||||
// hardware platforms, such as the Sun
|
||||
// SPARC, which don't like misaligned
|
||||
// data
|
||||
|
||||
// Positions
|
||||
double longitude; // geodetic (radians)
|
||||
|
@ -53,9 +57,11 @@ public:
|
|||
// Velocities
|
||||
double vcas; // calibrated airspeed
|
||||
double climb_rate; // feet per second
|
||||
|
||||
// Time
|
||||
time_t cur_time; // current unix time
|
||||
long int warp; // offset in seconds to unix time
|
||||
};
|
||||
|
||||
|
||||
#endif // _RAW_FDM_HXX
|
||||
|
||||
|
||||
#endif // _NET_FDM_HXX
|
Loading…
Reference in a new issue