1
0
Fork 0

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:
curt 2003-03-03 04:30:16 +00:00
parent 648f1208f8
commit cc269730a5
3 changed files with 299 additions and 0 deletions

View 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
}

View 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

View 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