First stab at a "named pipe" interface to an external FDM. Compared to the
ExternalNet interface: - allows a much more closely coupled execution. A remote network FDM will run at it's own rate, and maybe a particular data packets will come, maybe it won't. This makes it very hard to control timing and keep the animation smooth. There are also cpu scheduling issues with running multiple processes on a single machine. The linux scheduler by default runs at 100hz. If an FDM process uses a sleep/alarm system to avoid wasting CPU, it will be forced to run at 100hz, 50hz, 25hz, 20hz, etc. This makes it *impossible* to serve a display system running at 60hz without dropping frames. - the downside is that the FDM process must now run on the same machine as the master flightgear process.
This commit is contained in:
parent
648f1208f8
commit
cc269730a5
3 changed files with 299 additions and 0 deletions
224
src/FDM/ExternalPipe/ExternalPipe.cxx
Normal file
224
src/FDM/ExternalPipe/ExternalPipe.cxx
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
// ExternalPipe.hxx -- a "pipe" interface to an external flight dynamics model
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started March 2003.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2003 Curtis L. Olson - curt@flightgear.org
|
||||||
|
//
|
||||||
|
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( HAVE_SYS_TYPES_H ) && defined( HAVE_SYS_STAT_H )
|
||||||
|
# include <sys/types.h> // mkfifo() open() umask()
|
||||||
|
# include <sys/stat.h> // mkfifo() open() umask()
|
||||||
|
# include <fcntl.h> // open()
|
||||||
|
# include <unistd.h> // unlink()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <simgear/io/lowlevel.hxx> // endian tests
|
||||||
|
|
||||||
|
#include <Main/fg_props.hxx>
|
||||||
|
#include <Network/native_ctrls.hxx>
|
||||||
|
#include <Network/native_fdm.hxx>
|
||||||
|
|
||||||
|
#include "ExternalPipe.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
FGExternalPipe::FGExternalPipe( double dt, string name ) {
|
||||||
|
valid = true;
|
||||||
|
|
||||||
|
buf = new char[sizeof(ctrls) + 1];
|
||||||
|
|
||||||
|
#if defined( HAVE_SYS_TYPES_H ) && defined( HAVE_SYS_STAT_H )
|
||||||
|
fifo_name_1 = name + "1";
|
||||||
|
fifo_name_2 = name + "2";
|
||||||
|
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "ExternalPipe Inited with " << name );
|
||||||
|
|
||||||
|
// Make the named pipe
|
||||||
|
umask(0);
|
||||||
|
int result;
|
||||||
|
result = mkfifo( fifo_name_1.c_str(), 0644 );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to create named pipe: "
|
||||||
|
<< fifo_name_1 );
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
result = mkfifo( fifo_name_2.c_str(), 0644 );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to create named pipe: "
|
||||||
|
<< fifo_name_2 );
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pd1 = open( fifo_name_1.c_str(), O_RDWR );
|
||||||
|
cout << "pd1 = " << pd1 << endl;
|
||||||
|
if ( pd1 == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to open named pipe: " << fifo_name_1 );
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
pd2 = open( fifo_name_2.c_str(), O_RDWR );
|
||||||
|
cout << "pd2 = " << pd2 << endl;
|
||||||
|
if ( pd2 == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to open named pipe: " << fifo_name_2 );
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FGExternalPipe::~FGExternalPipe() {
|
||||||
|
delete [] buf;
|
||||||
|
|
||||||
|
#if defined( HAVE_SYS_TYPES_H ) && defined( HAVE_SYS_STAT_H )
|
||||||
|
// close
|
||||||
|
int result;
|
||||||
|
result = close( pd1 );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to close named pipe: "
|
||||||
|
<< fifo_name_1 );
|
||||||
|
}
|
||||||
|
result = close( pd2 );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to close named pipe: "
|
||||||
|
<< fifo_name_2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the file system entry
|
||||||
|
result = unlink( fifo_name_1.c_str() );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to remove named pipe: "
|
||||||
|
<< fifo_name_1 );
|
||||||
|
}
|
||||||
|
result = unlink( fifo_name_2.c_str() );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Unable to remove named pipe: "
|
||||||
|
<< fifo_name_2 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize the ExternalPipe flight model, dt is the time increment
|
||||||
|
// for each subsequent iteration through the EOM
|
||||||
|
void FGExternalPipe::init() {
|
||||||
|
// Explicitly call the superclass's
|
||||||
|
// init method first.
|
||||||
|
common_init();
|
||||||
|
|
||||||
|
double lon = fgGetDouble( "/sim/presets/longitude-deg" );
|
||||||
|
double lat = fgGetDouble( "/sim/presets/latitude-deg" );
|
||||||
|
double alt = fgGetDouble( "/sim/presets/altitude-ft" );
|
||||||
|
double ground = fgGetDouble( "/environment/ground-elevation-m" );
|
||||||
|
double heading = fgGetDouble("/sim/presets/heading-deg");
|
||||||
|
double speed = fgGetDouble( "/sim/presets/airspeed-kt" );
|
||||||
|
|
||||||
|
#if defined( HAVE_SYS_TYPES_H ) && defined( HAVE_SYS_STAT_H )
|
||||||
|
|
||||||
|
char cmd[256];
|
||||||
|
int result;
|
||||||
|
|
||||||
|
sprintf( cmd, "1longitude-deg=%.8f", lon );
|
||||||
|
result = std::write( pd1, cmd, strlen(cmd) );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( cmd, "1latitude-deg=%.8f", lat );
|
||||||
|
result = ::write( pd1, cmd, strlen(cmd) );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( cmd, "1altitude-ft=%.8f", alt );
|
||||||
|
result = std::write( pd1, cmd, strlen(cmd) );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( cmd, "1ground-m=%.8f", ground );
|
||||||
|
result = std::write( pd1, cmd, strlen(cmd) );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( cmd, "1speed-kts=%.8f", speed );
|
||||||
|
result = std::write( pd1, cmd, strlen(cmd) );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( cmd, "1heading-deg=%.8f", heading );
|
||||||
|
result = std::write( pd1, cmd, strlen(cmd) );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
SG_LOG( SG_IO, SG_INFO, "before sending reset command." );
|
||||||
|
|
||||||
|
if( fgGetBool("/sim/presets/onground") ) {
|
||||||
|
sprintf( cmd, "1reset=ground" );
|
||||||
|
} else {
|
||||||
|
sprintf( cmd, "1reset=air" );
|
||||||
|
}
|
||||||
|
result = std::write( pd1, cmd, strlen(cmd) );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
SG_LOG( SG_IO, SG_INFO, "Remote FDM init() finished." );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Run an iteration of the EOM.
|
||||||
|
void FGExternalPipe::update( double dt ) {
|
||||||
|
#if defined( HAVE_SYS_TYPES_H ) && defined( HAVE_SYS_STAT_H )
|
||||||
|
int length;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ( is_suspended() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send control positions to remote fdm
|
||||||
|
length = sizeof(ctrls);
|
||||||
|
FGProps2NetCtrls( &ctrls, false );
|
||||||
|
buf[0] = '2';
|
||||||
|
char *ptr = buf;
|
||||||
|
ptr++;
|
||||||
|
memcpy( ptr, (char *)(&ctrls), length );
|
||||||
|
result = std::write( pd1, buf, length + 1 );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
|
||||||
|
}
|
||||||
|
// cout << "wrote to pipe" << endl;
|
||||||
|
|
||||||
|
// Read next set of FDM data (blocking enabled to maintain 'sync')
|
||||||
|
length = sizeof(fdm);
|
||||||
|
result = std::read( pd2, (char *)(& fdm), length );
|
||||||
|
if ( result == -1 ) {
|
||||||
|
SG_LOG( SG_IO, SG_ALERT, "Read error from named pipe: "
|
||||||
|
<< fifo_name_2 );
|
||||||
|
}
|
||||||
|
FGNetFDM2Props( &fdm, false );
|
||||||
|
// cout << "read from pipe" << endl;
|
||||||
|
#endif
|
||||||
|
}
|
64
src/FDM/ExternalPipe/ExternalPipe.hxx
Normal file
64
src/FDM/ExternalPipe/ExternalPipe.hxx
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// ExternalPipe.hxx -- a "pipe" interface to an external flight dynamics model
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started March 2003.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2003 Curtis L. Olson - curt@flightgear.org
|
||||||
|
//
|
||||||
|
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
#ifndef _EXTERNAL_PIPE_HXX
|
||||||
|
#define _EXTERNAL_PIPE_HXX
|
||||||
|
|
||||||
|
#include <simgear/timing/timestamp.hxx> // fine grained timing measurements
|
||||||
|
|
||||||
|
#include <Network/net_ctrls.hxx>
|
||||||
|
#include <Network/net_fdm.hxx>
|
||||||
|
|
||||||
|
|
||||||
|
class FGExternalPipe: public FGInterface {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool valid;
|
||||||
|
|
||||||
|
string fifo_name_1;
|
||||||
|
string fifo_name_2;
|
||||||
|
int pd1;
|
||||||
|
int pd2;
|
||||||
|
|
||||||
|
FGNetCtrls ctrls;
|
||||||
|
FGNetFDM fdm;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
FGExternalPipe( double dt, string fifo_name );
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~FGExternalPipe();
|
||||||
|
|
||||||
|
// Reset flight params to a specific position
|
||||||
|
void init();
|
||||||
|
|
||||||
|
// update the fdm
|
||||||
|
void update( double dt );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _EXTERNAL_PIPE_HXX
|
11
src/FDM/ExternalPipe/Makefile.am
Normal file
11
src/FDM/ExternalPipe/Makefile.am
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
noinst_LIBRARIES = libExternalPipe.a
|
||||||
|
|
||||||
|
# noinst_PROGRAMS = demo_fdm
|
||||||
|
|
||||||
|
libExternalPipe_a_SOURCES = \
|
||||||
|
ExternalPipe.cxx ExternalPipe.hxx
|
||||||
|
|
||||||
|
# demo_fdm_SOURCES = demo_fdm.cxx demo_httpd.cxx demo_httpd.hxx
|
||||||
|
# demo_LDADD =
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
Loading…
Reference in a new issue