1
0
Fork 0

Merge all Net/DDS FDM, GUI and Ctrls struct handling into one source file and make it FlightGear agnostic which means that they can be used by, for instance, fgviewer.

This commit is contained in:
Erik Hofman 2021-03-23 14:30:52 +01:00
parent 8f5dc3e764
commit 875713efad
12 changed files with 1863 additions and 1793 deletions

View file

@ -31,6 +31,7 @@
#include <simgear/io/sg_netBuffer.hxx>
#include <Main/fg_props.hxx>
#include <Network/native_structs.hxx>
#include <Network/native_ctrls.hxx>
#include <Network/native_fdm.hxx>
@ -221,7 +222,7 @@ void FGExternalNet::update(double dt)
// Send control positions to remote fdm
length = sizeof(ctrls);
FGProps2Ctrls<FGNetCtrls>(&ctrls, true, true);
FGProps2Ctrls<FGNetCtrls>( globals->get_props(), &ctrls, true, true);
if (data_client.send((char*)(&ctrls), length, 0) != length) {
SG_LOG(SG_IO, SG_DEBUG, "Error writing data.");
} else {
@ -232,7 +233,7 @@ void FGExternalNet::update(double dt)
length = sizeof(fdm);
while ((result = data_server.recv((char*)(&fdm), length, 0)) >= 0) {
SG_LOG(SG_IO, SG_DEBUG, "Success reading data.");
FGFDM2Props<FGNetFDM>(&fdm);
FGFDM2Props<FGNetFDM>( globals->get_props(), &fdm);
}
}

View file

@ -40,6 +40,7 @@
#include <simgear/misc/strutils.hxx> // split()
#include <Main/fg_props.hxx>
#include <Network/native_structs.hxx>
#include <Network/native_ctrls.hxx>
#include <Network/native_fdm.hxx>
#include <Scenery/scenery.hxx>
@ -405,12 +406,12 @@ void FGExternalPipe::update_binary( double dt ) {
// Send control positions to remote fdm
length = sizeof(ctrls);
FGProps2Ctrls<FGNetCtrls>( &ctrls, true, false );
FGProps2Ctrls<FGNetCtrls>( globals->get_props(), &ctrls, true, false );
char *ptr = buf;
*((int *)ptr) = iterations;
// cout << "iterations = " << iterations << endl;
ptr += sizeof(int);
memcpy( ptr, (char *)(&ctrls), length );
memcpy( ptr, (char *)( globals->get_props(),&ctrls), length );
// cout << "writing control structure, size = "
// << length + sizeof(int) << endl;
@ -426,7 +427,7 @@ void FGExternalPipe::update_binary( double dt ) {
<< fifo_name_2 << " expected 1 item, but got " << result );
} else {
// cout << " read successful." << endl;
FGFDM2Props<FGNetFDM>( &fdm, false );
FGFDM2Props<FGNetFDM>( globals->get_props(), &fdm, false );
}
#endif
}

View file

@ -18,6 +18,7 @@ set(SOURCES
jsclient.cxx
lfsglass.cxx
native.cxx
native_structs.cxx
native_ctrls.cxx
native_fdm.cxx
native_gui.cxx
@ -48,6 +49,7 @@ set(HEADERS
jsclient.hxx
lfsglass.hxx
native.hxx
native_ctrls.hxx
native_ctrls.hxx
native_fdm.hxx
native_gui.hxx

View file

@ -93,9 +93,21 @@ int main()
* the buffer array to a valid sample memory location. */
samples[0] = FG_DDS_FDM__alloc ();
/* Poll until a keys is pressed */
// wait set
dds_entity_t waitset = dds_create_waitset(participant);
dds_entity_t rdcond = dds_create_readcondition(reader,
DDS_NOT_READ_SAMPLE_STATE);
int status = dds_waitset_attach(waitset, rdcond, reader);
if (status < 0)
DDS_FATAL("ds_waitset_attach: %s\n", dds_strretcode(-status));
/* Wait for a new packet. */
set_mode(1);
while( !get_key() )
size_t num = 1;
dds_attach_t results[num];
dds_duration_t timeout = DDS_MSECS(500);
while(dds_waitset_wait(waitset, results, num, timeout) >= 0)
{
/* Do the actual read.
* The return value contains the number of read samples. */
@ -117,11 +129,8 @@ int main()
fflush(stdout);
// break;
}
else
{
/* Polling sleep. */
dds_sleepfor(DDS_MSECS(20));
}
if (get_key()) break;
}
set_mode(0);

View file

@ -36,6 +36,7 @@
#include <Main/fg_props.hxx>
#include <Scenery/scenery.hxx> // ground elevation
#include "native_structs.hxx"
#include "native_ctrls.hxx"
// FreeBSD works better with this included last ... (?)
@ -47,645 +48,6 @@
# include <netinet/in.h> // htonl() ntohl()
#endif
// 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;
}
}
// Populate the FGNetCtrls structure from the property tree.
template<>
void FGProps2Ctrls<FGNetCtrls>( FGNetCtrls *net, bool honor_freezes,
bool net_byte_order )
{
int i;
SGPropertyNode *node;
SGPropertyNode *fuelpump;
SGPropertyNode *tempnode;
// fill in values
node = fgGetNode("/controls/flight", true);
net->version = FG_NET_CTRLS_VERSION;
net->aileron = node->getDoubleValue( "aileron" );
net->elevator = node->getDoubleValue( "elevator" );
net->rudder = node->getDoubleValue( "rudder" );
net->aileron_trim = node->getDoubleValue( "aileron-trim" );
net->elevator_trim = node->getDoubleValue( "elevator-trim" );
net->rudder_trim = node->getDoubleValue( "rudder-trim" );
net->flaps = node->getDoubleValue( "flaps" );
net->speedbrake = node->getDoubleValue( "speedbrake" );
net->spoilers = node->getDoubleValue( "spoilers" );
net->flaps_power
= fgGetDouble( "/systems/electrical/outputs/flaps", 1.0 ) >= 1.0;
net->flap_motor_ok = node->getBoolValue( "flaps-serviceable" );
net->num_engines = FGNetCtrls::FG_MAX_ENGINES;
for ( i = 0; i < FGNetCtrls::FG_MAX_ENGINES; ++i ) {
// Controls
node = fgGetNode("/controls/engines/engine", i );
fuelpump = fgGetNode("/systems/electrical/outputs/fuel-pump", i );
tempnode = node->getChild("starter");
if ( tempnode != NULL ) {
net->starter_power[i] = ( tempnode->getDoubleValue() >= 1.0 );
}
tempnode = node->getChild("master-bat");
if ( tempnode != NULL ) {
net->master_bat[i] = tempnode->getBoolValue();
}
tempnode = node->getChild("master-alt");
if ( tempnode != NULL ) {
net->master_alt[i] = tempnode->getBoolValue();
}
net->throttle[i] = node->getDoubleValue( "throttle", 0.0 );
net->mixture[i] = node->getDoubleValue( "mixture", 0.0 );
net->prop_advance[i] = node->getDoubleValue( "propeller-pitch", 0.0 );
net->condition[i] = node->getDoubleValue( "condition", 0.0 );
net->magnetos[i] = node->getIntValue( "magnetos", 0 );
if ( i == 0 ) {
// cout << "Magnetos -> " << node->getIntValue( "magnetos", 0 );
}
if ( i == 0 ) {
// cout << "Starter -> " << node->getIntValue( "starter", false )
// << endl;
}
if ( fuelpump != NULL ) {
net->fuel_pump_power[i] = ( fuelpump->getDoubleValue() >= 1.0 );
} else {
net->fuel_pump_power[i] = 0;
}
// Faults
SGPropertyNode *faults = node->getChild( "faults", 0, true );
net->engine_ok[i] = faults->getBoolValue( "serviceable", true );
net->mag_left_ok[i]
= faults->getBoolValue( "left-magneto-serviceable", true );
net->mag_right_ok[i]
= faults->getBoolValue( "right-magneto-serviceable", true);
net->spark_plugs_ok[i]
= faults->getBoolValue( "spark-plugs-serviceable", true );
net->oil_press_status[i]
= faults->getIntValue( "oil-pressure-status", 0 );
net->fuel_pump_ok[i]
= faults->getBoolValue( "fuel-pump-serviceable", true );
}
net->num_tanks = FGNetCtrls::FG_MAX_TANKS;
for ( i = 0; i < FGNetCtrls::FG_MAX_TANKS; ++i ) {
node = fgGetNode("/controls/fuel/tank", i);
if ( node->getChild("fuel_selector") != 0 ) {
net->fuel_selector[i]
= node->getChild("fuel_selector")->getBoolValue();
} else {
net->fuel_selector[i] = false;
}
}
node = fgGetNode("/controls/gear", true);
net->brake_left = node->getChild("brake-left")->getDoubleValue();
net->brake_right = node->getChild("brake-right")->getDoubleValue();
net->copilot_brake_left
= node->getChild("copilot-brake-left")->getDoubleValue();
net->copilot_brake_right
= node->getChild("copilot-brake-right")->getDoubleValue();
net->brake_parking = node->getChild("brake-parking")->getDoubleValue();
net->gear_handle = fgGetBool( "/controls/gear/gear-down" );
net->master_avionics = fgGetBool("/controls/switches/master-avionics");
net->wind_speed_kt = fgGetDouble("/environment/wind-speed-kt");
net->wind_dir_deg = fgGetDouble("/environment/wind-from-heading-deg");
net->turbulence_norm =
fgGetDouble("/environment/turbulence/magnitude-norm");
net->temp_c = fgGetDouble("/environment/temperature-degc");
net->press_inhg = fgGetDouble("/environment/pressure-sea-level-inhg");
net->hground = fgGetDouble("/position/ground-elev-m");
net->magvar = fgGetDouble("/environment/magnetic-variation-deg");
net->icing = fgGetBool("/hazards/icing/wing");
net->speedup = fgGetInt("/sim/speed-up");
net->freeze = 0;
if ( honor_freezes ) {
if ( fgGetBool("/sim/freeze/master") ) {
net->freeze |= 0x01;
}
if ( fgGetBool("/sim/freeze/position") ) {
net->freeze |= 0x02;
}
if ( fgGetBool("/sim/freeze/fuel") ) {
net->freeze |= 0x04;
}
}
if ( net_byte_order ) {
// convert to network byte order
net->version = htonl(net->version);
htond(net->aileron);
htond(net->elevator);
htond(net->rudder);
htond(net->aileron_trim);
htond(net->elevator_trim);
htond(net->rudder_trim);
htond(net->flaps);
htond(net->speedbrake);
htond(net->spoilers);
net->flaps_power = htonl(net->flaps_power);
net->flap_motor_ok = htonl(net->flap_motor_ok);
net->num_engines = htonl(net->num_engines);
for ( i = 0; i < FGNetCtrls::FG_MAX_ENGINES; ++i ) {
net->master_bat[i] = htonl(net->master_bat[i]);
net->master_alt[i] = htonl(net->master_alt[i]);
net->magnetos[i] = htonl(net->magnetos[i]);
net->starter_power[i] = htonl(net->starter_power[i]);
htond(net->throttle[i]);
htond(net->mixture[i]);
net->fuel_pump_power[i] = htonl(net->fuel_pump_power[i]);
htond(net->prop_advance[i]);
htond(net->condition[i]);
net->engine_ok[i] = htonl(net->engine_ok[i]);
net->mag_left_ok[i] = htonl(net->mag_left_ok[i]);
net->mag_right_ok[i] = htonl(net->mag_right_ok[i]);
net->spark_plugs_ok[i] = htonl(net->spark_plugs_ok[i]);
net->oil_press_status[i] = htonl(net->oil_press_status[i]);
net->fuel_pump_ok[i] = htonl(net->fuel_pump_ok[i]);
}
net->num_tanks = htonl(net->num_tanks);
for ( i = 0; i < FGNetCtrls::FG_MAX_TANKS; ++i ) {
net->fuel_selector[i] = htonl(net->fuel_selector[i]);
}
net->cross_feed = htonl(net->cross_feed);
htond(net->brake_left);
htond(net->brake_right);
htond(net->copilot_brake_left);
htond(net->copilot_brake_right);
htond(net->brake_parking);
net->gear_handle = htonl(net->gear_handle);
net->master_avionics = htonl(net->master_avionics);
htond(net->wind_speed_kt);
htond(net->wind_dir_deg);
htond(net->turbulence_norm);
htond(net->temp_c);
htond(net->press_inhg);
htond(net->hground);
htond(net->magvar);
net->icing = htonl(net->icing);
net->speedup = htonl(net->speedup);
net->freeze = htonl(net->freeze);
}
}
// Update the property tree from the FGNetCtrls structure.
template<>
void FGCtrls2Props<FGNetCtrls>( FGNetCtrls *net, bool honor_freezes,
bool net_byte_order )
{
int i;
SGPropertyNode * node;
if ( net_byte_order ) {
// convert from network byte order
net->version = htonl(net->version);
htond(net->aileron);
htond(net->elevator);
htond(net->rudder);
htond(net->aileron_trim);
htond(net->elevator_trim);
htond(net->rudder_trim);
htond(net->flaps);
htond(net->speedbrake);
htond(net->spoilers);
net->flaps_power = htonl(net->flaps_power);
net->flap_motor_ok = htonl(net->flap_motor_ok);
net->num_engines = htonl(net->num_engines);
for ( i = 0; i < (int)net->num_engines; ++i ) {
net->master_bat[i] = htonl(net->master_bat[i]);
net->master_alt[i] = htonl(net->master_alt[i]);
net->magnetos[i] = htonl(net->magnetos[i]);
net->starter_power[i] = htonl(net->starter_power[i]);
htond(net->throttle[i]);
htond(net->mixture[i]);
net->fuel_pump_power[i] = htonl(net->fuel_pump_power[i]);
htond(net->prop_advance[i]);
htond(net->condition[i]);
net->engine_ok[i] = htonl(net->engine_ok[i]);
net->mag_left_ok[i] = htonl(net->mag_left_ok[i]);
net->mag_right_ok[i] = htonl(net->mag_right_ok[i]);
net->spark_plugs_ok[i] = htonl(net->spark_plugs_ok[i]);
net->oil_press_status[i] = htonl(net->oil_press_status[i]);
net->fuel_pump_ok[i] = htonl(net->fuel_pump_ok[i]);
}
net->num_tanks = htonl(net->num_tanks);
for ( i = 0; i < FGNetCtrls::FG_MAX_TANKS; ++i ) {
net->fuel_selector[i] = htonl(net->fuel_selector[i]);
}
net->cross_feed = htonl(net->cross_feed);
htond(net->brake_left);
htond(net->brake_right);
htond(net->copilot_brake_left);
htond(net->copilot_brake_right);
htond(net->brake_parking);
net->gear_handle = htonl(net->gear_handle);
net->master_avionics = htonl(net->master_avionics);
htond(net->wind_speed_kt);
htond(net->wind_dir_deg);
htond(net->turbulence_norm);
htond(net->temp_c);
htond(net->press_inhg);
htond(net->hground);
htond(net->magvar);
net->icing = htonl(net->icing);
net->speedup = htonl(net->speedup);
net->freeze = htonl(net->freeze);
}
if ( net->version != FG_NET_CTRLS_VERSION ) {
SG_LOG( SG_IO, SG_ALERT,
"Version mismatch with raw controls packet format." );
SG_LOG( SG_IO, SG_ALERT,
"FlightGear needs version = " << FG_NET_CTRLS_VERSION
<< " but is receiving version = " << net->version );
}
node = fgGetNode("/controls/flight", true);
node->setDoubleValue( "aileron", net->aileron );
node->setDoubleValue( "elevator", net->elevator );
node->setDoubleValue( "rudder", net->rudder );
node->setDoubleValue( "aileron-trim", net->aileron_trim );
node->setDoubleValue( "elevator-trim", net->elevator_trim );
node->setDoubleValue( "rudder-trim", net->rudder_trim );
node->setDoubleValue( "flaps", net->flaps );
node->setDoubleValue( "speedbrake", net->speedbrake ); //JWW
// or
node->setDoubleValue( "spoilers", net->spoilers ); //JWW
// cout << "NET->Spoilers: " << net->spoilers << endl;
fgSetBool( "/systems/electrical/outputs/flaps", net->flaps_power > 0 );
node->setBoolValue( "flaps-serviceable", net->flap_motor_ok > 0 );
for ( i = 0; i < FGNetCtrls::FG_MAX_ENGINES; ++i ) {
// Controls
node = fgGetNode("/controls/engines/engine", i);
node->getChild( "throttle" )->setDoubleValue( net->throttle[i] );
node->getChild( "mixture" )->setDoubleValue( net->mixture[i] );
node->getChild( "propeller-pitch" )
->setDoubleValue( net->prop_advance[i] );
node->getChild( "condition" )
->setDoubleValue( net->condition[i] );
node->getChild( "magnetos" )->setDoubleValue( net->magnetos[i] );
node->getChild( "starter" )->setDoubleValue( net->starter_power[i] );
node->getChild( "feed_tank" )->setIntValue( net->feed_tank_to[i] );
node->getChild( "reverser" )->setBoolValue( net->reverse[i] > 0 );
// Faults
SGPropertyNode *faults = node->getNode( "faults", true );
faults->setBoolValue( "serviceable", net->engine_ok[i] > 0 );
faults->setBoolValue( "left-magneto-serviceable",
net->mag_left_ok[i] > 0 );
faults->setBoolValue( "right-magneto-serviceable",
net->mag_right_ok[i] > 0);
faults->setBoolValue( "spark-plugs-serviceable",
net->spark_plugs_ok[i] > 0);
faults->setIntValue( "oil-pressure-status", net->oil_press_status[i] );
faults->setBoolValue( "fuel-pump-serviceable", net->fuel_pump_ok[i] > 0);
}
fgSetBool( "/systems/electrical/outputs/fuel-pump",
net->fuel_pump_power[0] > 0);
for ( i = 0; i < FGNetCtrls::FG_MAX_TANKS; ++i ) {
node = fgGetNode( "/controls/fuel/tank", i );
node->getChild( "fuel_selector" )
->setBoolValue( net->fuel_selector[i] > 0 );
// node->getChild( "to_tank" )->xfer_tank( i, net->xfer_to[i] );
}
node = fgGetNode( "/controls/gear" );
if ( node != NULL ) {
node->getChild( "brake-left" )->setDoubleValue( net->brake_left );
node->getChild( "brake-right" )->setDoubleValue( net->brake_right );
node->getChild( "copilot-brake-left" )
->setDoubleValue( net->copilot_brake_left );
node->getChild( "copilot-brake-right" )
->setDoubleValue( net->copilot_brake_right );
node->getChild( "brake-parking" )->setDoubleValue( net->brake_parking );
}
node = fgGetNode( "/controls/gear", true );
node->setBoolValue( "gear-down", net->gear_handle > 0 );
// node->setDoubleValue( "brake-parking", net->brake_parking );
// node->setDoubleValue( net->brake_left );
// node->setDoubleValue( net->brake_right );
node = fgGetNode( "/controls/switches", true );
node->setBoolValue( "master-bat", net->master_bat[0] != 0 );
node->setBoolValue( "master-alt", net->master_alt[0] != 0 );
node->setBoolValue( "master-avionics", net->master_avionics > 0 );
node = fgGetNode( "/environment", true );
node->setDoubleValue( "wind-speed-kt", net->wind_speed_kt );
node->setDoubleValue( "wind-from-heading-deg", net->wind_dir_deg );
node->setDoubleValue( "turbulence/magnitude-norm", net->turbulence_norm );
node->setDoubleValue( "magnetic-variation-deg", net->magvar );
node->setDoubleValue( "/environment/temperature-degc",
net->temp_c );
node->setDoubleValue( "/environment/pressure-sea-level-inhg",
net->press_inhg );
// ground elevation ???
fgSetDouble("/hazards/icing/wing", net->icing);
node = fgGetNode( "/radios", true );
node->setDoubleValue( "comm/frequencies/selected-mhz[0]", net->comm_1 );
node->setDoubleValue( "nav/frequencies/selected-mhz[0]", net->nav_1 );
node->setDoubleValue( "nav[1]/frequencies/selected-mhz[0]", net->nav_2 );
fgSetDouble( "/sim/speed-up", net->speedup );
if ( honor_freezes ) {
node = fgGetNode( "/sim/freeze", true );
node->setBoolValue( "master", (net->freeze & 0x01) > 0 );
node->setBoolValue( "position", (net->freeze & 0x02) > 0 );
node->setBoolValue( "fuel", (net->freeze & 0x04) > 0 );
}
}
#if FG_HAVE_DDS
// Populate the FG_DDS_Ctrls structure from the property tree.
template<>
void FGProps2Ctrls<FG_DDS_Ctrls>( FG_DDS_Ctrls *dds, bool honor_freezes, bool net_byte_order )
{
int i;
SGPropertyNode *node;
SGPropertyNode *fuelpump;
SGPropertyNode *tempnode;
// fill in values
node = fgGetNode("/controls/flight", true);
dds->version = FG_DDS_CTRLS_VERSION;
dds->aileron = node->getDoubleValue( "aileron" );
dds->elevator = node->getDoubleValue( "elevator" );
dds->rudder = node->getDoubleValue( "rudder" );
dds->aileron_trim = node->getDoubleValue( "aileron-trim" );
dds->elevator_trim = node->getDoubleValue( "elevator-trim" );
dds->rudder_trim = node->getDoubleValue( "rudder-trim" );
dds->flaps = node->getDoubleValue( "flaps" );
dds->speedbrake = node->getDoubleValue( "speedbrake" );
dds->spoilers = node->getDoubleValue( "spoilers" );
dds->flaps_power
= fgGetDouble( "/systems/electrical/outputs/flaps", 1.0 ) >= 1.0;
dds->flap_motor_ok = node->getBoolValue( "flaps-serviceable" );
dds->num_engines = FGNetCtrls::FG_MAX_ENGINES;
for ( i = 0; i < FGNetCtrls::FG_MAX_ENGINES; ++i ) {
// Controls
node = fgGetNode("/controls/engines/engine", i );
fuelpump = fgGetNode("/systems/electrical/outputs/fuel-pump", i );
tempnode = node->getChild("starter");
if ( tempnode != NULL ) {
dds->starter_power[i] = ( tempnode->getDoubleValue() >= 1.0 );
}
tempnode = node->getChild("master-bat");
if ( tempnode != NULL ) {
dds->master_bat[i] = tempnode->getBoolValue();
}
tempnode = node->getChild("master-alt");
if ( tempnode != NULL ) {
dds->master_alt[i] = tempnode->getBoolValue();
}
dds->throttle[i] = node->getDoubleValue( "throttle", 0.0 );
dds->mixture[i] = node->getDoubleValue( "mixture", 0.0 );
dds->prop_advance[i] = node->getDoubleValue( "propeller-pitch", 0.0 );
dds->condition[i] = node->getDoubleValue( "condition", 0.0 );
dds->magnetos[i] = node->getIntValue( "magnetos", 0 );
if ( i == 0 ) {
// cout << "Magnetos -> " << node->getIntValue( "magnetos", 0 );
}
if ( i == 0 ) {
// cout << "Starter -> " << node->getIntValue( "starter", false )
// << endl;
}
if ( fuelpump != NULL ) {
dds->fuel_pump_power[i] = ( fuelpump->getDoubleValue() >= 1.0 );
} else {
dds->fuel_pump_power[i] = 0;
}
// Faults
SGPropertyNode *faults = node->getChild( "faults", 0, true );
dds->engine_ok[i] = faults->getBoolValue( "serviceable", true );
dds->mag_left_ok[i]
= faults->getBoolValue( "left-magneto-serviceable", true );
dds->mag_right_ok[i]
= faults->getBoolValue( "right-magneto-serviceable", true);
dds->spark_plugs_ok[i]
= faults->getBoolValue( "spark-plugs-serviceable", true );
dds->oil_press_status[i]
= faults->getIntValue( "oil-pressure-status", 0 );
dds->fuel_pump_ok[i]
= faults->getBoolValue( "fuel-pump-serviceable", true );
}
dds->num_tanks = FGNetCtrls::FG_MAX_TANKS;
for ( i = 0; i < FGNetCtrls::FG_MAX_TANKS; ++i ) {
node = fgGetNode("/controls/fuel/tank", i);
if ( node->getChild("fuel_selector") != 0 ) {
dds->fuel_selector[i]
= node->getChild("fuel_selector")->getBoolValue();
} else {
dds->fuel_selector[i] = false;
}
}
node = fgGetNode("/controls/gear", true);
dds->brake_left = node->getChild("brake-left")->getDoubleValue();
dds->brake_right = node->getChild("brake-right")->getDoubleValue();
dds->copilot_brake_left
= node->getChild("copilot-brake-left")->getDoubleValue();
dds->copilot_brake_right
= node->getChild("copilot-brake-right")->getDoubleValue();
dds->brake_parking = node->getChild("brake-parking")->getDoubleValue();
dds->gear_handle = fgGetBool( "/controls/gear/gear-down" );
dds->master_avionics = fgGetBool("/controls/switches/master-avionics");
dds->wind_speed_kt = fgGetDouble("/environment/wind-speed-kt");
dds->wind_dir_deg = fgGetDouble("/environment/wind-from-heading-deg");
dds->turbulence_norm =
fgGetDouble("/environment/turbulence/magnitude-norm");
dds->temp_c = fgGetDouble("/environment/temperature-degc");
dds->press_inhg = fgGetDouble("/environment/pressure-sea-level-inhg");
dds->hground = fgGetDouble("/position/ground-elev-m");
dds->magvar = fgGetDouble("/environment/magnetic-variation-deg");
dds->icing = fgGetBool("/hazards/icing/wing");
dds->speedup = fgGetInt("/sim/speed-up");
dds->freeze = 0;
if ( honor_freezes ) {
if ( fgGetBool("/sim/freeze/master") ) {
dds->freeze |= 0x01;
}
if ( fgGetBool("/sim/freeze/position") ) {
dds->freeze |= 0x02;
}
if ( fgGetBool("/sim/freeze/fuel") ) {
dds->freeze |= 0x04;
}
}
}
// Update the property tree from the FG_DDS_Ctrls structure.
template<>
void FGCtrls2Props<FG_DDS_Ctrls>( FG_DDS_Ctrls *dds, bool honor_freezes, bool net_byte_order )
{
int i;
SGPropertyNode * node;
if ( dds->version != FG_DDS_CTRLS_VERSION ) {
SG_LOG( SG_IO, SG_ALERT,
"Version mismatch with raw controls packet format." );
SG_LOG( SG_IO, SG_ALERT,
"FlightGear needs version = " << FG_DDS_CTRLS_VERSION
<< " but is receiving version = " << dds->version );
}
node = fgGetNode("/controls/flight", true);
node->setDoubleValue( "aileron", dds->aileron );
node->setDoubleValue( "elevator", dds->elevator );
node->setDoubleValue( "rudder", dds->rudder );
node->setDoubleValue( "aileron-trim", dds->aileron_trim );
node->setDoubleValue( "elevator-trim", dds->elevator_trim );
node->setDoubleValue( "rudder-trim", dds->rudder_trim );
node->setDoubleValue( "flaps", dds->flaps );
node->setDoubleValue( "speedbrake", dds->speedbrake ); //JWW
// or
node->setDoubleValue( "spoilers", dds->spoilers ); //JWW
// cout << "NET->Spoilers: " << dds->spoilers << endl;
fgSetBool( "/systems/electrical/outputs/flaps", dds->flaps_power > 0 );
node->setBoolValue( "flaps-serviceable", dds->flap_motor_ok > 0 );
for ( i = 0; i < FGNetCtrls::FG_MAX_ENGINES; ++i ) {
// Controls
node = fgGetNode("/controls/engines/engine", i);
node->getChild( "throttle" )->setDoubleValue( dds->throttle[i] );
node->getChild( "mixture" )->setDoubleValue( dds->mixture[i] );
node->getChild( "propeller-pitch" )
->setDoubleValue( dds->prop_advance[i] );
node->getChild( "condition" )
->setDoubleValue( dds->condition[i] );
node->getChild( "magnetos" )->setDoubleValue( dds->magnetos[i] );
node->getChild( "starter" )->setDoubleValue( dds->starter_power[i] );
node->getChild( "feed_tank" )->setIntValue( dds->feed_tank_to[i] );
node->getChild( "reverser" )->setBoolValue( dds->reverse[i] > 0 );
// Faults
SGPropertyNode *faults = node->getNode( "faults", true );
faults->setBoolValue( "serviceable", dds->engine_ok[i] > 0 );
faults->setBoolValue( "left-magneto-serviceable",
dds->mag_left_ok[i] > 0 );
faults->setBoolValue( "right-magneto-serviceable",
dds->mag_right_ok[i] > 0);
faults->setBoolValue( "spark-plugs-serviceable",
dds->spark_plugs_ok[i] > 0);
faults->setIntValue( "oil-pressure-status", dds->oil_press_status[i] );
faults->setBoolValue( "fuel-pump-serviceable", dds->fuel_pump_ok[i] > 0);
}
fgSetBool( "/systems/electrical/outputs/fuel-pump",
dds->fuel_pump_power[0] > 0);
for ( i = 0; i < FGNetCtrls::FG_MAX_TANKS; ++i ) {
node = fgGetNode( "/controls/fuel/tank", i );
node->getChild( "fuel_selector" )
->setBoolValue( dds->fuel_selector[i] > 0 );
// node->getChild( "to_tank" )->xfer_tank( i, dds->xfer_to[i] );
}
node = fgGetNode( "/controls/gear" );
if ( node != NULL ) {
node->getChild( "brake-left" )->setDoubleValue( dds->brake_left );
node->getChild( "brake-right" )->setDoubleValue( dds->brake_right );
node->getChild( "copilot-brake-left" )
->setDoubleValue( dds->copilot_brake_left );
node->getChild( "copilot-brake-right" )
->setDoubleValue( dds->copilot_brake_right );
node->getChild( "brake-parking" )->setDoubleValue( dds->brake_parking );
}
node = fgGetNode( "/controls/gear", true );
node->setBoolValue( "gear-down", dds->gear_handle > 0 );
// node->setDoubleValue( "brake-parking", dds->brake_parking );
// node->setDoubleValue( dds->brake_left );
// node->setDoubleValue( dds->brake_right );
node = fgGetNode( "/controls/switches", true );
node->setBoolValue( "master-bat", dds->master_bat[0] != 0 );
node->setBoolValue( "master-alt", dds->master_alt[0] != 0 );
node->setBoolValue( "master-avionics", dds->master_avionics > 0 );
node = fgGetNode( "/environment", true );
node->setDoubleValue( "wind-speed-kt", dds->wind_speed_kt );
node->setDoubleValue( "wind-from-heading-deg", dds->wind_dir_deg );
node->setDoubleValue( "turbulence/magnitude-norm", dds->turbulence_norm );
node->setDoubleValue( "magnetic-variation-deg", dds->magvar );
node->setDoubleValue( "/environment/temperature-degc",
dds->temp_c );
node->setDoubleValue( "/environment/pressure-sea-level-inhg",
dds->press_inhg );
// ground elevation ???
fgSetDouble("/hazards/icing/wing", dds->icing);
node = fgGetNode( "/radios", true );
node->setDoubleValue( "comm/frequencies/selected-mhz[0]", dds->comm_1 );
node->setDoubleValue( "nav/frequencies/selected-mhz[0]", dds->nav_1 );
node->setDoubleValue( "nav[1]/frequencies/selected-mhz[0]", dds->nav_2 );
fgSetDouble( "/sim/speed-up", dds->speedup );
if ( honor_freezes ) {
node = fgGetNode( "/sim/freeze", true );
node->setBoolValue( "master", (dds->freeze & 0x01) > 0 );
node->setBoolValue( "position", (dds->freeze & 0x02) > 0 );
node->setBoolValue( "fuel", (dds->freeze & 0x04) > 0 );
}
}
#endif
// open hailing frequencies
bool FGNativeCtrls::open() {
if ( is_enabled() ) {
@ -730,9 +92,9 @@ bool FGNativeCtrls::process() {
if ( get_direction() == SG_IO_OUT )
{
if ( io->get_type() == sgDDSType ) {
FGProps2Ctrls( &ctrls.dds, true, true );
FGProps2Ctrls( globals->get_props(), &ctrls.dds, true, true );
} else {
FGProps2Ctrls( &ctrls.net, true, true );
FGProps2Ctrls( globals->get_props(), &ctrls.net, true, true );
}
if ( ! io->write( buf, length ) ) {
@ -745,17 +107,17 @@ bool FGNativeCtrls::process() {
if ( io->get_type() == sgFileType ) {
if ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_INFO, "Success reading data." );
FGCtrls2Props( &ctrls.net, true, true );
FGCtrls2Props( globals->get_props(), &ctrls.net, true, true );
}
} else if ( io->get_type() == sgDDSType ) {
while ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_INFO, "Success reading data." );
FGCtrls2Props( &ctrls.dds, true, true );
FGCtrls2Props( globals->get_props(), &ctrls.dds, true, true );
}
} else {
while ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_INFO, "Success reading data." );
FGCtrls2Props( &ctrls.net, true, true );
FGCtrls2Props( globals->get_props(), &ctrls.net, true, true );
}
}
}

View file

@ -61,17 +61,4 @@ public:
bool close();
};
// Helper functions which may be useful outside this class
// Populate the FGNetCtrls/FG_DDS_Ctrls structure from the property tree.
template<typename T>
void FGProps2Ctrls( T *net, bool honor_freezes, bool net_byte_order );
// Update the property tree from the FGNetCtrls/FG_DDS_Ctrls structure.
template<typename T>
void FGCtrls2Props( T *net, bool honor_freezes, bool net_byte_order );
#endif // _FG_NATIVE_CTRLS_HXX

View file

@ -26,7 +26,6 @@
#endif
#include <simgear/debug/logstream.hxx>
#include <simgear/io/lowlevel.hxx> // endian tests
#include <simgear/io/iochannel.hxx>
#include <simgear/timing/sg_time.hxx>
@ -39,6 +38,7 @@
#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
#include "native_structs.hxx"
#include "native_fdm.hxx"
// FreeBSD works better with this included last ... (?)
@ -50,682 +50,6 @@
# include <netinet/in.h> // htonl() ntohl()
#endif
// 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;
}
}
// Float version
static void htonf (float &x)
{
if ( sgIsLittleEndian() ) {
int *Float_Overlay;
int Holding_Buffer;
Float_Overlay = (int *) &x;
Holding_Buffer = Float_Overlay [0];
Float_Overlay [0] = htonl (Holding_Buffer);
} else {
return;
}
}
template<>
void FGProps2FDM<FGNetFDM>( FGNetFDM *net, bool net_byte_order ) {
unsigned int i;
FlightProperties fdm_state;
// Version sanity checking
net->version = FG_NET_FDM_VERSION;
// Aero parameters
net->longitude = fdm_state.get_Longitude();
net->latitude = fdm_state.get_Latitude();
net->altitude = fdm_state.get_Altitude() * SG_FEET_TO_METER;
net->agl = fdm_state.get_Altitude_AGL() * SG_FEET_TO_METER;
net->phi = fdm_state.get_Phi();
net->theta = fdm_state.get_Theta();
net->psi = fdm_state.get_Psi();
net->alpha = fdm_state.get_Alpha();
net->beta = fdm_state.get_Beta();
net->phidot = fdm_state.get_Phi_dot_degps() * SG_DEGREES_TO_RADIANS;
net->thetadot = fdm_state.get_Theta_dot_degps()
* SG_DEGREES_TO_RADIANS;
net->psidot = fdm_state.get_Psi_dot_degps() * SG_DEGREES_TO_RADIANS;
net->vcas = fdm_state.get_V_calibrated_kts();
net->climb_rate = fdm_state.get_Climb_Rate();
net->v_north = fdm_state.get_V_north();
net->v_east = fdm_state.get_V_east();
net->v_down = fdm_state.get_V_down();
net->v_body_u = fdm_state.get_uBody();
net->v_body_v = fdm_state.get_vBody();
net->v_body_w = fdm_state.get_wBody();
net->A_X_pilot = fdm_state.get_A_X_pilot();
net->A_Y_pilot = fdm_state.get_A_Y_pilot();
net->A_Z_pilot = fdm_state.get_A_Z_pilot();
net->stall_warning = fgGetDouble("/sim/alarms/stall-warning", 0.0);
net->slip_deg
= fgGetDouble("/instrumentation/slip-skid-ball/indicated-slip-skid");
// Engine parameters
net->num_engines = FGNetFDM::FG_MAX_ENGINES;
for ( i = 0; i < net->num_engines; ++i ) {
SGPropertyNode *node = fgGetNode("engines/engine", i, true);
if ( node->getBoolValue( "running" ) ) {
net->eng_state[i] = 2;
} else if ( node->getBoolValue( "cranking" ) ) {
net->eng_state[i] = 1;
} else {
net->eng_state[i] = 0;
}
net->rpm[i] = node->getDoubleValue( "rpm" );
net->fuel_flow[i] = node->getDoubleValue( "fuel-flow-gph" );
net->fuel_px[i] = node->getDoubleValue( "fuel-px-psi" );
net->egt[i] = node->getDoubleValue( "egt-degf" );
// cout << "egt = " << aero->EGT << endl;
net->cht[i] = node->getDoubleValue( "cht-degf" );
net->mp_osi[i] = node->getDoubleValue( "mp-osi" );
net->tit[i] = node->getDoubleValue( "tit" );
net->oil_temp[i] = node->getDoubleValue( "oil-temperature-degf" );
net->oil_px[i] = node->getDoubleValue( "oil-pressure-psi" );
}
// Consumables
net->num_tanks = FGNetFDM::FG_MAX_TANKS;
for ( i = 0; i < net->num_tanks; ++i ) {
SGPropertyNode *node = fgGetNode("/consumables/fuel/tank", i, true);
net->fuel_quantity[i] = node->getDoubleValue("level-gal_us");
net->tank_selected[i] = node->getBoolValue("selected");
net->capacity_m3[i] = node->getDoubleValue("capacity-m3");
net->unusable_m3[i] = node->getDoubleValue("unusable-m3");
net->density_kgpm3[i] = node->getDoubleValue("density-kgpm3");
net->level_m3[i] = node->getDoubleValue("level-m3");
}
// Gear and flaps
net->num_wheels = FGNetFDM::FG_MAX_WHEELS;
for (i = 0; i < net->num_wheels; ++i ) {
SGPropertyNode *node = fgGetNode("/gear/gear", i, true);
net->wow[i] = node->getIntValue("wow");
net->gear_pos[i] = node->getDoubleValue("position-norm");
net->gear_steer[i] = node->getDoubleValue("steering-norm");
net->gear_compression[i] = node->getDoubleValue("compression-norm");
}
// the following really aren't used in this context
net->cur_time = globals->get_time_params()->get_cur_time();
net->warp = globals->get_warp();
net->visibility = fgGetDouble("/environment/visibility-m");
// Control surface positions
SGPropertyNode *node = fgGetNode("/surface-positions", true);
net->elevator = node->getDoubleValue( "elevator-pos-norm" );
net->elevator_trim_tab
= node->getDoubleValue( "elevator-trim-tab-pos-norm" );
// FIXME: CLO 10/28/04 - This really should be separated out into 2 values
net->left_flap = node->getDoubleValue( "flap-pos-norm" );
net->right_flap = node->getDoubleValue( "flap-pos-norm" );
net->left_aileron = node->getDoubleValue( "left-aileron-pos-norm" );
net->right_aileron = node->getDoubleValue( "right-aileron-pos-norm" );
net->rudder = node->getDoubleValue( "rudder-pos-norm" );
net->nose_wheel = node->getDoubleValue( "nose-wheel-pos-norm" );
net->speedbrake = node->getDoubleValue( "speedbrake-pos-norm" );
net->spoilers = node->getDoubleValue( "spoilers-pos-norm" );
if ( net_byte_order ) {
// Convert the net buffer to network format
net->version = htonl(net->version);
htond(net->longitude);
htond(net->latitude);
htond(net->altitude);
htonf(net->agl);
htonf(net->phi);
htonf(net->theta);
htonf(net->psi);
htonf(net->alpha);
htonf(net->beta);
htonf(net->phidot);
htonf(net->thetadot);
htonf(net->psidot);
htonf(net->vcas);
htonf(net->climb_rate);
htonf(net->v_north);
htonf(net->v_east);
htonf(net->v_down);
htonf(net->v_body_u);
htonf(net->v_body_v);
htonf(net->v_body_w);
htonf(net->A_X_pilot);
htonf(net->A_Y_pilot);
htonf(net->A_Z_pilot);
htonf(net->stall_warning);
htonf(net->slip_deg);
for ( i = 0; i < net->num_engines; ++i ) {
net->eng_state[i] = htonl(net->eng_state[i]);
htonf(net->rpm[i]);
htonf(net->fuel_flow[i]);
htonf(net->fuel_px[i]);
htonf(net->egt[i]);
htonf(net->cht[i]);
htonf(net->mp_osi[i]);
htonf(net->tit[i]);
htonf(net->oil_temp[i]);
htonf(net->oil_px[i]);
}
net->num_engines = htonl(net->num_engines);
for ( i = 0; i < net->num_tanks; ++i ) {
htonf(net->fuel_quantity[i]);
htonl(net->tank_selected[i]);
htond(net->capacity_m3[i]);
htond(net->unusable_m3[i]);
htond(net->density_kgpm3[i]);
htond(net->level_m3[i]);
}
net->num_tanks = htonl(net->num_tanks);
for ( i = 0; i < net->num_wheels; ++i ) {
net->wow[i] = htonl(net->wow[i]);
htonf(net->gear_pos[i]);
htonf(net->gear_steer[i]);
htonf(net->gear_compression[i]);
}
net->num_wheels = htonl(net->num_wheels);
net->cur_time = htonl( net->cur_time );
net->warp = htonl( net->warp );
htonf(net->visibility);
htonf(net->elevator);
htonf(net->elevator_trim_tab);
htonf(net->left_flap);
htonf(net->right_flap);
htonf(net->left_aileron);
htonf(net->right_aileron);
htonf(net->rudder);
htonf(net->nose_wheel);
htonf(net->speedbrake);
htonf(net->spoilers);
}
}
template<>
void FGFDM2Props<FGNetFDM>( FGNetFDM *net, bool net_byte_order ) {
unsigned int i;
FlightProperties fdm_state;
if ( net_byte_order ) {
// Convert to the net buffer from network format
net->version = ntohl(net->version);
htond(net->longitude);
htond(net->latitude);
htond(net->altitude);
htonf(net->agl);
htonf(net->phi);
htonf(net->theta);
htonf(net->psi);
htonf(net->alpha);
htonf(net->beta);
htonf(net->phidot);
htonf(net->thetadot);
htonf(net->psidot);
htonf(net->vcas);
htonf(net->climb_rate);
htonf(net->v_north);
htonf(net->v_east);
htonf(net->v_down);
htonf(net->v_body_u);
htonf(net->v_body_v);
htonf(net->v_body_w);
htonf(net->A_X_pilot);
htonf(net->A_Y_pilot);
htonf(net->A_Z_pilot);
htonf(net->stall_warning);
htonf(net->slip_deg);
net->num_engines = htonl(net->num_engines);
for ( i = 0; i < net->num_engines; ++i ) {
net->eng_state[i] = htonl(net->eng_state[i]);
htonf(net->rpm[i]);
htonf(net->fuel_flow[i]);
htonf(net->fuel_px[i]);
htonf(net->egt[i]);
htonf(net->cht[i]);
htonf(net->mp_osi[i]);
htonf(net->tit[i]);
htonf(net->oil_temp[i]);
htonf(net->oil_px[i]);
}
net->num_tanks = htonl(net->num_tanks);
for ( i = 0; i < net->num_tanks; ++i ) {
htonf(net->fuel_quantity[i]);
htonl(net->tank_selected[i]);
htond(net->capacity_m3[i]);
htond(net->unusable_m3[i]);
htond(net->density_kgpm3[i]);
htond(net->level_m3[i]);
}
net->num_wheels = htonl(net->num_wheels);
for ( i = 0; i < net->num_wheels; ++i ) {
net->wow[i] = htonl(net->wow[i]);
htonf(net->gear_pos[i]);
htonf(net->gear_steer[i]);
htonf(net->gear_compression[i]);
}
net->cur_time = htonl(net->cur_time);
net->warp = ntohl(net->warp);
htonf(net->visibility);
htonf(net->elevator);
htonf(net->elevator_trim_tab);
htonf(net->left_flap);
htonf(net->right_flap);
htonf(net->left_aileron);
htonf(net->right_aileron);
htonf(net->rudder);
htonf(net->nose_wheel);
htonf(net->speedbrake);
htonf(net->spoilers);
}
if ( net->version == FG_NET_FDM_VERSION ) {
// cout << "pos = " << net->longitude << " " << net->latitude << endl;
// cout << "sea level rad = " << fdm_state.get_Sea_level_radius()
// << endl;
fdm_state.set_Latitude(net->latitude);
fdm_state.set_Longitude(net->longitude);
fdm_state.set_Altitude(net->altitude * SG_METER_TO_FEET);
if ( net->agl > -9000 ) {
fdm_state.set_Altitude_AGL( net->agl * SG_METER_TO_FEET );
} else {
double agl_m = net->altitude
- fdm_state.get_Runway_altitude_m();
fdm_state.set_Altitude_AGL( agl_m * SG_METER_TO_FEET );
}
fdm_state.set_Euler_Angles( net->phi,
net->theta,
net->psi );
fdm_state.set_Alpha( net->alpha );
fdm_state.set_Beta( net->beta );
fdm_state.set_Euler_Rates( net->phidot,
net->thetadot,
net->psidot );
fdm_state.set_V_calibrated_kts( net->vcas );
fdm_state.set_Climb_Rate( net->climb_rate );
fdm_state.set_Velocities_Local( net->v_north,
net->v_east,
net->v_down );
fdm_state.set_Velocities_Body( net->v_body_u,
net->v_body_v,
net->v_body_w );
fdm_state.set_Accels_Pilot_Body( net->A_X_pilot,
net->A_Y_pilot,
net->A_Z_pilot );
fgSetDouble( "/sim/alarms/stall-warning", net->stall_warning );
fgSetDouble( "/instrumentation/slip-skid-ball/indicated-slip-skid",
net->slip_deg );
fgSetBool( "/instrumentation/slip-skid-ball/override", true );
for ( i = 0; i < net->num_engines; ++i ) {
SGPropertyNode *node = fgGetNode( "engines/engine", i, true );
// node->setBoolValue("running", t->isRunning());
// node->setBoolValue("cranking", t->isCranking());
// cout << net->eng_state[i] << endl;
if ( net->eng_state[i] == 0 ) {
node->setBoolValue( "cranking", false );
node->setBoolValue( "running", false );
} else if ( net->eng_state[i] == 1 ) {
node->setBoolValue( "cranking", true );
node->setBoolValue( "running", false );
} else if ( net->eng_state[i] == 2 ) {
node->setBoolValue( "cranking", false );
node->setBoolValue( "running", true );
}
node->setDoubleValue( "rpm", net->rpm[i] );
node->setDoubleValue( "fuel-flow-gph", net->fuel_flow[i] );
node->setDoubleValue( "fuel-px-psi", net->fuel_px[i] );
node->setDoubleValue( "egt-degf", net->egt[i] );
node->setDoubleValue( "cht-degf", net->cht[i] );
node->setDoubleValue( "mp-osi", net->mp_osi[i] );
node->setDoubleValue( "tit", net->tit[i] );
node->setDoubleValue( "oil-temperature-degf", net->oil_temp[i] );
node->setDoubleValue( "oil-pressure-psi", net->oil_px[i] );
}
for (i = 0; i < net->num_tanks; ++i ) {
SGPropertyNode * node
= fgGetNode("/consumables/fuel/tank", i, true);
node->setDoubleValue("level-gal_us", net->fuel_quantity[i]);
node->setBoolValue("selected", net->tank_selected[i] > 0);
node->setDoubleValue("capacity-m3", net->capacity_m3[i]);
node->setDoubleValue("unusable-m3", net->unusable_m3[i]);
node->setDoubleValue("density-kgpm3", net->density_kgpm3[i]);
node->setDoubleValue("level-m3", net->level_m3[i]);
}
for (i = 0; i < net->num_wheels; ++i ) {
SGPropertyNode * node = fgGetNode("/gear/gear", i, true);
node->setDoubleValue("wow", net->wow[i] );
node->setDoubleValue("position-norm", net->gear_pos[i] );
node->setDoubleValue("steering-norm", net->gear_steer[i] );
node->setDoubleValue("compression-norm", net->gear_compression[i] );
}
/* these are ignored for now ... */
/*
if ( net->cur_time ) {
fgSetLong("/sim/time/cur-time-override", net->cur_time);
}
globals->set_warp( net->warp );
last_warp = net->warp;
*/
SGPropertyNode *node = fgGetNode("/surface-positions", true);
node->setDoubleValue("elevator-pos-norm", net->elevator);
node->setDoubleValue("elevator-trim-tab-pos-norm",
net->elevator_trim_tab);
// FIXME: CLO 10/28/04 - This really should be separated out
// into 2 values
node->setDoubleValue("flap-pos-norm", net->left_flap);
node->setDoubleValue("flap-pos-norm", net->right_flap);
node->setDoubleValue("left-aileron-pos-norm", net->left_aileron);
node->setDoubleValue("right-aileron-pos-norm", net->right_aileron);
node->setDoubleValue("rudder-pos-norm", net->rudder);
node->setDoubleValue("nose-wheel-pos-norm", net->nose_wheel);
node->setDoubleValue("speedbrake-pos-norm", net->speedbrake);
node->setDoubleValue("spoilers-pos-norm", net->spoilers);
} else {
SG_LOG( SG_IO, SG_ALERT,
"Error: version mismatch in Net FGFDM2Props()" );
SG_LOG( SG_IO, SG_ALERT,
"\tread " << net->version << " need " << FG_NET_FDM_VERSION );
SG_LOG( SG_IO, SG_ALERT,
"\tNeeds to upgrade net_fdm.hxx and recompile." );
}
}
#if FG_HAVE_DDS
template<>
void FGProps2FDM<FG_DDS_FDM>( FG_DDS_FDM *dds, bool net_byte_order ) {
unsigned int i;
FlightProperties fdm_state;
// Version sanity checking
dds->version = FG_DDS_FDM_VERSION;
// Aero parameters
dds->longitude = fdm_state.get_Longitude();
dds->latitude = fdm_state.get_Latitude();
dds->altitude = fdm_state.get_Altitude() * SG_FEET_TO_METER;
dds->agl = fdm_state.get_Altitude_AGL() * SG_FEET_TO_METER;
dds->phi = fdm_state.get_Phi();
dds->theta = fdm_state.get_Theta();
dds->psi = fdm_state.get_Psi();
dds->alpha = fdm_state.get_Alpha();
dds->beta = fdm_state.get_Beta();
dds->phidot = fdm_state.get_Phi_dot_degps() * SG_DEGREES_TO_RADIANS;
dds->thetadot = fdm_state.get_Theta_dot_degps() * SG_DEGREES_TO_RADIANS;
dds->psidot = fdm_state.get_Psi_dot_degps() * SG_DEGREES_TO_RADIANS;
dds->vcas = fdm_state.get_V_calibrated_kts();
dds->climb_rate = fdm_state.get_Climb_Rate();
dds->v_north = fdm_state.get_V_north();
dds->v_east = fdm_state.get_V_east();
dds->v_down = fdm_state.get_V_down();
dds->v_body_u = fdm_state.get_uBody();
dds->v_body_v = fdm_state.get_vBody();
dds->v_body_w = fdm_state.get_wBody();
dds->A_X_pilot = fdm_state.get_A_X_pilot();
dds->A_Y_pilot = fdm_state.get_A_Y_pilot();
dds->A_Z_pilot = fdm_state.get_A_Z_pilot();
dds->stall_warning = fgGetDouble("/sim/alarms/stall-warning", 0.0);
dds->slip_deg
= fgGetDouble("/instrumentation/slip-skid-ball/indicated-slip-skid");
// Engine parameters
dds->num_engines = FGNetFDM::FG_MAX_ENGINES;
for ( i = 0; i < dds->num_engines; ++i ) {
SGPropertyNode *node = fgGetNode("engines/engine", i, true);
if ( node->getBoolValue( "running" ) ) {
dds->eng_state[i] = 2;
} else if ( node->getBoolValue( "cranking" ) ) {
dds->eng_state[i] = 1;
} else {
dds->eng_state[i] = 0;
}
dds->rpm[i] = node->getDoubleValue( "rpm" );
dds->fuel_flow[i] = node->getDoubleValue( "fuel-flow-gph" );
dds->fuel_px[i] = node->getDoubleValue( "fuel-px-psi" );
dds->egt[i] = node->getDoubleValue( "egt-degf" );
// cout << "egt = " << aero->EGT << endl;
dds->cht[i] = node->getDoubleValue( "cht-degf" );
dds->mp_osi[i] = node->getDoubleValue( "mp-osi" );
dds->tit[i] = node->getDoubleValue( "tit" );
dds->oil_temp[i] = node->getDoubleValue( "oil-temperature-degf" );
dds->oil_px[i] = node->getDoubleValue( "oil-pressure-psi" );
}
// Consumables
dds->num_tanks = FGNetFDM::FG_MAX_TANKS;
for ( i = 0; i < dds->num_tanks; ++i ) {
SGPropertyNode *node = fgGetNode("/consumables/fuel/tank", i, true);
dds->fuel_quantity[i] = node->getDoubleValue("level-gal_us");
dds->tank_selected[i] = node->getBoolValue("selected");
dds->capacity_m3[i] = node->getDoubleValue("capacity-m3");
dds->unusable_m3[i] = node->getDoubleValue("unusable-m3");
dds->density_kgpm3[i] = node->getDoubleValue("density-kgpm3");
dds->level_m3[i] = node->getDoubleValue("level-m3");
}
// Gear and flaps
dds->num_wheels = FGNetFDM::FG_MAX_WHEELS;
for (i = 0; i < dds->num_wheels; ++i ) {
SGPropertyNode *node = fgGetNode("/gear/gear", i, true);
dds->wow[i] = node->getIntValue("wow");
dds->gear_pos[i] = node->getDoubleValue("position-norm");
dds->gear_steer[i] = node->getDoubleValue("steering-norm");
dds->gear_compression[i] = node->getDoubleValue("compression-norm");
}
// the following really aren't used in this context
dds->cur_time = globals->get_time_params()->get_cur_time();
dds->warp = globals->get_warp();
dds->visibility = fgGetDouble("/environment/visibility-m");
// Control surface positions
SGPropertyNode *node = fgGetNode("/surface-positions", true);
dds->elevator = node->getDoubleValue( "elevator-pos-norm" );
dds->elevator_trim_tab
= node->getDoubleValue( "elevator-trim-tab-pos-norm" );
// FIXME: CLO 10/28/04 - This really should be separated out into 2 values
dds->left_flap = node->getDoubleValue( "flap-pos-norm" );
dds->right_flap = node->getDoubleValue( "flap-pos-norm" );
dds->left_aileron = node->getDoubleValue( "left-aileron-pos-norm" );
dds->right_aileron = node->getDoubleValue( "right-aileron-pos-norm" );
dds->rudder = node->getDoubleValue( "rudder-pos-norm" );
dds->nose_wheel = node->getDoubleValue( "nose-wheel-pos-norm" );
dds->speedbrake = node->getDoubleValue( "speedbrake-pos-norm" );
dds->spoilers = node->getDoubleValue( "spoilers-pos-norm" );
}
template<>
void FGFDM2Props<FG_DDS_FDM>( FG_DDS_FDM *dds, bool net_byte_order ) {
unsigned int i;
FlightProperties fdm_state;
if ( dds->version == FG_DDS_FDM_VERSION ) {
// cout << "pos = " << dds->longitude << " " << dds->latitude << endl;
// cout << "sea level rad = " << fdm_state.get_Sea_level_radius()
// << endl;
fdm_state.set_Latitude(dds->latitude);
fdm_state.set_Longitude(dds->longitude);
fdm_state.set_Altitude(dds->altitude * SG_METER_TO_FEET);
if ( dds->agl > -9000 ) {
fdm_state.set_Altitude_AGL( dds->agl * SG_METER_TO_FEET );
} else {
double agl_m = dds->altitude
- fdm_state.get_Runway_altitude_m();
fdm_state.set_Altitude_AGL( agl_m * SG_METER_TO_FEET );
}
fdm_state.set_Euler_Angles( dds->phi,
dds->theta,
dds->psi );
fdm_state.set_Alpha( dds->alpha );
fdm_state.set_Beta( dds->beta );
fdm_state.set_Euler_Rates( dds->phidot,
dds->thetadot,
dds->psidot );
fdm_state.set_V_calibrated_kts( dds->vcas );
fdm_state.set_Climb_Rate( dds->climb_rate );
fdm_state.set_Velocities_Local( dds->v_north,
dds->v_east,
dds->v_down );
fdm_state.set_Velocities_Body( dds->v_body_u,
dds->v_body_v,
dds->v_body_w );
fdm_state.set_Accels_Pilot_Body( dds->A_X_pilot,
dds->A_Y_pilot,
dds->A_Z_pilot );
fgSetDouble( "/sim/alarms/stall-warning", dds->stall_warning );
fgSetDouble( "/instrumentation/slip-skid-ball/indicated-slip-skid",
dds->slip_deg );
fgSetBool( "/instrumentation/slip-skid-ball/override", true );
for ( i = 0; i < dds->num_engines; ++i ) {
SGPropertyNode *node = fgGetNode( "engines/engine", i, true );
// node->setBoolValue("running", t->isRunning());
// node->setBoolValue("cranking", t->isCranking());
// cout << dds->eng_state[i] << endl;
if ( dds->eng_state[i] == 0 ) {
node->setBoolValue( "cranking", false );
node->setBoolValue( "running", false );
} else if ( dds->eng_state[i] == 1 ) {
node->setBoolValue( "cranking", true );
node->setBoolValue( "running", false );
} else if ( dds->eng_state[i] == 2 ) {
node->setBoolValue( "cranking", false );
node->setBoolValue( "running", true );
}
node->setDoubleValue( "rpm", dds->rpm[i] );
node->setDoubleValue( "fuel-flow-gph", dds->fuel_flow[i] );
node->setDoubleValue( "fuel-px-psi", dds->fuel_px[i] );
node->setDoubleValue( "egt-degf", dds->egt[i] );
node->setDoubleValue( "cht-degf", dds->cht[i] );
node->setDoubleValue( "mp-osi", dds->mp_osi[i] );
node->setDoubleValue( "tit", dds->tit[i] );
node->setDoubleValue( "oil-temperature-degf", dds->oil_temp[i] );
node->setDoubleValue( "oil-pressure-psi", dds->oil_px[i] );
}
for (i = 0; i < dds->num_tanks; ++i ) {
SGPropertyNode * node
= fgGetNode("/consumables/fuel/tank", i, true);
node->setDoubleValue("level-gal_us", dds->fuel_quantity[i]);
node->setBoolValue("selected", dds->tank_selected[i] > 0);
node->setDoubleValue("capacity-m3", dds->capacity_m3[i]);
node->setDoubleValue("unusable-m3", dds->unusable_m3[i]);
node->setDoubleValue("density-kgpm3", dds->density_kgpm3[i]);
node->setDoubleValue("level-m3", dds->level_m3[i]);
}
for (i = 0; i < dds->num_wheels; ++i ) {
SGPropertyNode * node = fgGetNode("/gear/gear", i, true);
node->setDoubleValue("wow", dds->wow[i] );
node->setDoubleValue("position-norm", dds->gear_pos[i] );
node->setDoubleValue("steering-norm", dds->gear_steer[i] );
node->setDoubleValue("compression-norm", dds->gear_compression[i] );
}
/* these are ignored for now ... */
/*
if ( dds->cur_time ) {
fgSetLong("/sim/time/cur-time-override", dds->cur_time);
}
globals->set_warp( dds->warp );
last_warp = dds->warp;
*/
SGPropertyNode *node = fgGetNode("/surface-positions", true);
node->setDoubleValue("elevator-pos-norm", dds->elevator);
node->setDoubleValue("elevator-trim-tab-pos-norm",
dds->elevator_trim_tab);
// FIXME: CLO 10/28/04 - This really should be separated out
// into 2 values
node->setDoubleValue("flap-pos-norm", dds->left_flap);
node->setDoubleValue("flap-pos-norm", dds->right_flap);
node->setDoubleValue("left-aileron-pos-norm", dds->left_aileron);
node->setDoubleValue("right-aileron-pos-norm", dds->right_aileron);
node->setDoubleValue("rudder-pos-norm", dds->rudder);
node->setDoubleValue("nose-wheel-pos-norm", dds->nose_wheel);
node->setDoubleValue("speedbrake-pos-norm", dds->speedbrake);
node->setDoubleValue("spoilers-pos-norm", dds->spoilers);
} else {
SG_LOG( SG_IO, SG_ALERT,
"Error: version mismatch in DDS FGFDM2Props()" );
SG_LOG( SG_IO, SG_ALERT,
"\tread " << dds->version << " need " << FG_DDS_FDM_VERSION );
SG_LOG( SG_IO, SG_ALERT,
"\tNeeds to upgrade DDS/dds_fdm.hxx and recompile." );
}
}
#endif
// open hailing frequencies
bool FGNativeFDM::open() {
if ( is_enabled() ) {
@ -773,9 +97,9 @@ bool FGNativeFDM::process() {
if ( get_direction() == SG_IO_OUT ) {
if ( io->get_type() == sgDDSType ) {
FGProps2FDM( &fdm.dds );
FGProps2FDM( globals->get_props(), &fdm.dds );
} else {
FGProps2FDM( &fdm.net );
FGProps2FDM( globals->get_props(), &fdm.net );
}
if ( ! io->write( buf, length ) ) {
@ -786,17 +110,17 @@ bool FGNativeFDM::process() {
if ( io->get_type() == sgFileType ) {
if ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_INFO, "Success reading data." );
FGFDM2Props( &fdm.net );
FGFDM2Props( globals->get_props(), &fdm.net );
}
} else if ( io->get_type() == sgDDSType ) {
while ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_INFO, " Success reading data." );
FGFDM2Props( &fdm.dds );
FGFDM2Props( globals->get_props(), &fdm.dds );
}
} else {
while ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_INFO, " Success reading data." );
FGFDM2Props( &fdm.net );
FGFDM2Props( globals->get_props(), &fdm.net );
}
}
}

View file

@ -60,17 +60,4 @@ public:
bool close();
};
// Helper functions which may be useful outside this class
// Populate the FGNetFDM/FG_DDS_FDM structure from the property tree.
template<typename T>
void FGProps2FDM( T *net, bool net_byte_order = true );
// Update the property tree from the FGNetFDM/FG_DDS_FDM structure.
template<typename T>
void FGFDM2Props( T *net, bool net_byte_order = true );
#endif // _FG_NATIVE_FDM_HXX

View file

@ -40,6 +40,7 @@
#include <Scenery/scenery.hxx>
#include <FDM/flightProperties.hxx>
#include "native_structs.hxx"
#include "native_gui.hxx"
// FreeBSD works better with this included last ... (?)
@ -51,416 +52,6 @@
# include <netinet/in.h> // htonl() ntohl()
#endif
// #define FG_USE_NETWORK_BYTE_ORDER
#if defined( FG_USE_NETWORK_BYTE_ORDER )
// 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;
}
}
static void htonf (float &x)
{
if ( sgIsLittleEndian() ) {
int *Float_Overlay;
int Holding_Buffer;
Float_Overlay = (int *) &x;
Holding_Buffer = Float_Overlay [0];
Float_Overlay [0] = htonl (Holding_Buffer);
} else {
return;
}
}
#endif
template<>
void FGProps2GUI<FGNetGUI>( FGNetGUI *net ) {
static SGPropertyNode *nav_freq
= fgGetNode("/instrumentation/nav/frequencies/selected-mhz", true);
static SGPropertyNode *nav_target_radial
= fgGetNode("/instrumentation/nav/radials/target-radial-deg", true);
static SGPropertyNode *nav_inrange
= fgGetNode("/instrumentation/nav/in-range", true);
static SGPropertyNode *nav_loc
= fgGetNode("/instrumentation/nav/nav-loc", true);
static SGPropertyNode *nav_gs_dist_signed
= fgGetNode("/instrumentation/nav/gs-distance", true);
static SGPropertyNode *nav_loc_dist
= fgGetNode("/instrumentation/nav/nav-distance", true);
static SGPropertyNode *nav_reciprocal_radial
= fgGetNode("/instrumentation/nav/radials/reciprocal-radial-deg", true);
static SGPropertyNode *nav_gs_deflection
= fgGetNode("/instrumentation/nav/gs-needle-deflection", true);
unsigned int i;
static FlightProperties* fdm_state = new FlightProperties;
// Version sanity checking
net->version = FG_NET_GUI_VERSION;
// Aero parameters
net->longitude = fdm_state->get_Longitude();
net->latitude = fdm_state->get_Latitude();
net->altitude = fdm_state->get_Altitude() * SG_FEET_TO_METER;
net->phi = fdm_state->get_Phi();
net->theta = fdm_state->get_Theta();
net->psi = fdm_state->get_Psi();
// Velocities
net->vcas = fdm_state->get_V_calibrated_kts();
net->climb_rate = fdm_state->get_Climb_Rate();
// Consumables
net->num_tanks = FGNetGUI::FG_MAX_TANKS;
for ( i = 0; i < net->num_tanks; ++i ) {
SGPropertyNode *node = fgGetNode("/consumables/fuel/tank", i, true);
net->fuel_quantity[i] = node->getDoubleValue("level-gal_us");
}
// Environment
net->cur_time = globals->get_time_params()->get_cur_time();
net->warp = globals->get_warp();
net->ground_elev = fdm_state->get_Runway_altitude_m();
// Approach
net->tuned_freq = nav_freq->getDoubleValue();
net->nav_radial = nav_target_radial->getDoubleValue();
net->in_range = nav_inrange->getBoolValue();
if ( nav_loc->getBoolValue() ) {
// is an ILS
net->dist_nm
= nav_gs_dist_signed->getDoubleValue()
* SG_METER_TO_NM;
} else {
// is a VOR
net->dist_nm = nav_loc_dist->getDoubleValue()
* SG_METER_TO_NM;
}
net->course_deviation_deg
= nav_reciprocal_radial->getDoubleValue()
- nav_target_radial->getDoubleValue();
if ( net->course_deviation_deg < -1000.0
|| net->course_deviation_deg > 1000.0 )
{
// Sanity check ...
net->course_deviation_deg = 0.0;
}
while ( net->course_deviation_deg > 180.0 ) {
net->course_deviation_deg -= 360.0;
}
while ( net->course_deviation_deg < -180.0 ) {
net->course_deviation_deg += 360.0;
}
if ( fabs(net->course_deviation_deg) > 90.0 )
net->course_deviation_deg
= ( net->course_deviation_deg<0.0
? -net->course_deviation_deg - 180.0
: -net->course_deviation_deg + 180.0 );
if ( nav_loc->getBoolValue() ) {
// is an ILS
net->gs_deviation_deg
= nav_gs_deflection->getDoubleValue()
/ 5.0;
} else {
// is an ILS
net->gs_deviation_deg = -9999.0;
}
#if defined( FG_USE_NETWORK_BYTE_ORDER )
// Convert the net buffer to network format
net->version = htonl(net->version);
htond(net->longitude);
htond(net->latitude);
htonf(net->altitude);
htonf(net->phi);
htonf(net->theta);
htonf(net->psi);
htonf(net->vcas);
htonf(net->climb_rate);
for ( i = 0; i < net->num_tanks; ++i ) {
htonf(net->fuel_quantity[i]);
}
net->num_tanks = htonl(net->num_tanks);
net->cur_time = htonl( net->cur_time );
net->warp = htonl( net->warp );
net->ground_elev = htonl( net->ground_elev );
htonf(net->tuned_freq);
htonf(net->nav_radial);
net->in_range = htonl( net->in_range );
htonf(net->dist_nm);
htonf(net->course_deviation_deg);
htonf(net->gs_deviation_deg);
#endif
}
template<>
void FGGUI2Props<FGNetGUI>( FGNetGUI *net ) {
unsigned int i;
#if defined( FG_USE_NETWORK_BYTE_ORDER )
// Convert to the net buffer from network format
net->version = ntohl(net->version);
htond(net->longitude);
htond(net->latitude);
htonf(net->altitude);
htonf(net->phi);
htonf(net->theta);
htonf(net->psi);
htonf(net->vcas);
htonf(net->climb_rate);
net->num_tanks = htonl(net->num_tanks);
for ( i = 0; i < net->num_tanks; ++i ) {
htonf(net->fuel_quantity[i]);
}
net->cur_time = ntohl(net->cur_time);
net->warp = ntohl(net->warp);
net->ground_elev = htonl( net->ground_elev );
htonf(net->tuned_freq);
htonf(net->nav_radial);
net->in_range = htonl( net->in_range );
htonf(net->dist_nm);
htonf(net->course_deviation_deg);
htonf(net->gs_deviation_deg);
#endif
if ( net->version == FG_NET_GUI_VERSION ) {
FlightProperties fdm_state;
// cout << "pos = " << net->longitude << " " << net->latitude << endl;
// cout << "sea level rad = " << fdm_state->get_Sea_level_radius()
// << endl;
fdm_state.set_Latitude(net->latitude);
fdm_state.set_Longitude(net->longitude);
fdm_state.set_Altitude(net->altitude * SG_METER_TO_FEET);
fdm_state.set_Euler_Angles( net->phi,
net->theta,
net->psi );
fdm_state.set_V_calibrated_kts( net->vcas );
fdm_state.set_Climb_Rate( net->climb_rate );
for (i = 0; i < net->num_tanks; ++i ) {
SGPropertyNode * node
= fgGetNode("/consumables/fuel/tank", i, true);
node->setDoubleValue("level-gal_us", net->fuel_quantity[i] );
}
if ( net->cur_time ) {
fgSetLong("/sim/time/cur-time-override", net->cur_time);
}
globals->set_warp( net->warp );
// Approach
fgSetDouble( "/instrumentation/nav[0]/frequencies/selected-mhz",
net->tuned_freq );
fgSetBool( "/instrumentation/nav[0]/in-range", net->in_range > 0);
fgSetDouble( "/instrumentation/dme/indicated-distance-nm", net->dist_nm );
fgSetDouble( "/instrumentation/nav[0]/heading-needle-deflection",
net->course_deviation_deg );
fgSetDouble( "/instrumentation/nav[0]/gs-needle-deflection",
net->gs_deviation_deg );
} else {
SG_LOG( SG_IO, SG_ALERT,
"Error: version mismatch in FGNetNativeGUI2Props()" );
SG_LOG( SG_IO, SG_ALERT,
"\tread " << net->version << " need " << FG_NET_GUI_VERSION );
SG_LOG( SG_IO, SG_ALERT,
"\tNeed to upgrade net_fdm.hxx and recompile." );
}
}
#if FG_HAVE_DDS
template<>
void FGProps2GUI<FG_DDS_GUI>( FG_DDS_GUI *dds ) {
static SGPropertyNode *nav_freq
= fgGetNode("/instrumentation/nav/frequencies/selected-mhz", true);
static SGPropertyNode *nav_target_radial
= fgGetNode("/instrumentation/nav/radials/target-radial-deg", true);
static SGPropertyNode *nav_inrange
= fgGetNode("/instrumentation/nav/in-range", true);
static SGPropertyNode *nav_loc
= fgGetNode("/instrumentation/nav/nav-loc", true);
static SGPropertyNode *nav_gs_dist_signed
= fgGetNode("/instrumentation/nav/gs-distance", true);
static SGPropertyNode *nav_loc_dist
= fgGetNode("/instrumentation/nav/nav-distance", true);
static SGPropertyNode *nav_reciprocal_radial
= fgGetNode("/instrumentation/nav/radials/reciprocal-radial-deg", true);
static SGPropertyNode *nav_gs_deflection
= fgGetNode("/instrumentation/nav/gs-needle-deflection", true);
unsigned int i;
static FlightProperties* fdm_state = new FlightProperties;
// Version sanity checking
dds->version = FG_DDS_GUI_VERSION;
// Aero parameters
dds->longitude = fdm_state->get_Longitude();
dds->latitude = fdm_state->get_Latitude();
dds->altitude = fdm_state->get_Altitude() * SG_FEET_TO_METER;
dds->phi = fdm_state->get_Phi();
dds->theta = fdm_state->get_Theta();
dds->psi = fdm_state->get_Psi();
// Velocities
dds->vcas = fdm_state->get_V_calibrated_kts();
dds->climb_rate = fdm_state->get_Climb_Rate();
// Consumables
dds->num_tanks = FGNetGUI::FG_MAX_TANKS;
for ( i = 0; i < dds->num_tanks; ++i ) {
SGPropertyNode *node = fgGetNode("/consumables/fuel/tank", i, true);
dds->fuel_quantity[i] = node->getDoubleValue("level-gal_us");
}
// Environment
dds->cur_time = globals->get_time_params()->get_cur_time();
dds->warp = globals->get_warp();
dds->ground_elev = fdm_state->get_Runway_altitude_m();
// Approach
dds->tuned_freq = nav_freq->getDoubleValue();
dds->nav_radial = nav_target_radial->getDoubleValue();
dds->in_range = nav_inrange->getBoolValue();
if ( nav_loc->getBoolValue() ) {
// is an ILS
dds->dist_nm
= nav_gs_dist_signed->getDoubleValue()
* SG_METER_TO_NM;
} else {
// is a VOR
dds->dist_nm = nav_loc_dist->getDoubleValue()
* SG_METER_TO_NM;
}
dds->course_deviation_deg
= nav_reciprocal_radial->getDoubleValue()
- nav_target_radial->getDoubleValue();
if ( dds->course_deviation_deg < -1000.0
|| dds->course_deviation_deg > 1000.0 )
{
// Sanity check ...
dds->course_deviation_deg = 0.0;
}
while ( dds->course_deviation_deg > 180.0 ) {
dds->course_deviation_deg -= 360.0;
}
while ( dds->course_deviation_deg > 180.0 ) {
dds->course_deviation_deg -= 360.0;
}
while ( dds->course_deviation_deg < -180.0 ) {
dds->course_deviation_deg += 360.0;
}
if ( fabs(dds->course_deviation_deg) > 90.0 )
dds->course_deviation_deg
= ( dds->course_deviation_deg<0.0
? -dds->course_deviation_deg - 180.0
: -dds->course_deviation_deg + 180.0 );
if ( nav_loc->getBoolValue() ) {
// is an ILS
dds->gs_deviation_deg
= nav_gs_deflection->getDoubleValue()
/ 5.0;
} else {
// is an ILS
dds->gs_deviation_deg = -9999.0;
}
}
template<>
void FGGUI2Props<FG_DDS_GUI>( FG_DDS_GUI *dds ) {
unsigned int i;
if ( dds->version == FG_DDS_GUI_VERSION ) {
FlightProperties fdm_state;
// cout << "pos = " << dds->longitude << " " << dds->latitude << endl;
// cout << "sea level rad = " << fdm_state->get_Sea_level_radius()
// << endl;
fdm_state.set_Latitude(dds->latitude);
fdm_state.set_Longitude(dds->longitude);
fdm_state.set_Altitude(dds->altitude * SG_METER_TO_FEET);
fdm_state.set_Euler_Angles( dds->phi,
dds->theta,
dds->psi );
fdm_state.set_V_calibrated_kts( dds->vcas );
fdm_state.set_Climb_Rate( dds->climb_rate );
for (i = 0; i < dds->num_tanks; ++i ) {
SGPropertyNode * node
= fgGetNode("/consumables/fuel/tank", i, true);
node->setDoubleValue("level-gal_us", dds->fuel_quantity[i] );
}
if ( dds->cur_time ) {
fgSetLong("/sim/time/cur-time-override", dds->cur_time);
}
globals->set_warp( dds->warp );
// Approach
fgSetDouble( "/instrumentation/nav[0]/frequencies/selected-mhz",
dds->tuned_freq );
fgSetBool( "/instrumentation/nav[0]/in-range", dds->in_range > 0);
fgSetDouble( "/instrumentation/dme/indicated-distance-nm", dds->dist_nm );
fgSetDouble( "/instrumentation/nav[0]/heading-needle-deflection",
dds->course_deviation_deg );
fgSetDouble( "/instrumentation/nav[0]/gs-needle-deflection",
dds->gs_deviation_deg );
} else {
SG_LOG( SG_IO, SG_ALERT,
"Error: version mismatch in FGNetNativeGUI2Props()" );
SG_LOG( SG_IO, SG_ALERT,
"\tread " << dds->version << " need " << FG_DDS_GUI_VERSION );
SG_LOG( SG_IO, SG_ALERT,
"\tNeed to upgrade net_fdm.hxx and recompile." );
}
}
#endif
// open hailing frequencies
bool FGNativeGUI::open() {
if ( is_enabled() ) {
@ -506,9 +97,9 @@ bool FGNativeGUI::process() {
if ( get_direction() == SG_IO_OUT ) {
// cout << "size of fdm_state = " << length << endl;
if ( io->get_type() == sgDDSType ) {
FGProps2GUI( &gui.dds );
FGProps2GUI( globals->get_props(), &gui.dds );
} else {
FGProps2GUI( &gui.net );
FGProps2GUI( globals->get_props(), &gui.net );
}
if ( ! io->write( buf, length ) ) {
@ -519,17 +110,17 @@ bool FGNativeGUI::process() {
if ( io->get_type() == sgFileType ) {
if ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
FGGUI2Props( &gui.net );
FGGUI2Props( globals->get_props(), &gui.net );
}
} if ( io->get_type() == sgDDSType ) {
while ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
FGGUI2Props( &gui.dds );
FGGUI2Props( globals->get_props(), &gui.dds );
}
} else {
while ( io->read( buf, length ) == length ) {
SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
FGGUI2Props( &gui.net );
FGGUI2Props( globals->get_props(), &gui.net );
}
}
}

View file

@ -57,18 +57,4 @@ public:
bool close();
};
// Helper functions which may be useful outside this class
// Populate the FGNetGUI/FG_DDS_GUI structure from the property tree.
template<typename T>
void FGProps2GUI( T *net );
// Update the property tree from the FGNetGUI/FG_DDS_GUI structure.
template<typename T>
void FGGUI2Props( T *net );
#endif // _FG_NATIVE_GUI_HXX

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
// native_fdm.hxx -- FGFS "Native" flight dynamics protocal class
//
// Written by Curtis Olson, started September 2001.
//
// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#pragma once
// Helper functions which may be useful outside this class
// Populate the FGNetFDM/FG_DDS_FDM structure from the property tree.
template<typename T>
void FGProps2FDM( SGPropertyNode *props, T *net, bool net_byte_order = true );
// Update the property tree from the FGNetFDM/FG_DDS_FDM structure.
template<typename T>
void FGFDM2Props( SGPropertyNode *props, T *net, bool net_byte_order = true );
// Populate the FGNetGUI/FG_DDS_GUI structure from the property tree.
template<typename T>
void FGProps2GUI( SGPropertyNode *props, T *net );
// Update the property tree from the FGNetGUI/FG_DDS_GUI structure.
template<typename T>
void FGGUI2Props( SGPropertyNode *props, T *net );
// Populate the FGNetCtrls/FG_DDS_Ctrls structure from the property tree.
template<typename T>
void FGProps2Ctrls( SGPropertyNode *props, T *net, bool honor_freezes, bool net_byte_order );
// Update the property tree from the FGNetCtrls/FG_DDS_Ctrls structure.
template<typename T>
void FGCtrls2Props( SGPropertyNode *props, T *net, bool honor_freezes, bool net_byte_order );