13# include <sys/types.h>
23#include <simgear/debug/logstream.hxx>
24#include <simgear/io/lowlevel.hxx>
25#include <simgear/misc/strutils.hxx>
43 last_cg_offset = -9999.9;
48 property_names.clear();
52 fifo_name_1 =
name +
"1";
53 fifo_name_2 =
name +
"2";
55 SG_LOG( SG_IO, SG_ALERT,
"ExternalPipe Inited with " <<
name );
60 result = mkfifo( fifo_name_1.c_str(), 0644 );
62 SG_LOG( SG_IO, SG_ALERT,
"Unable to create named pipe: "
64 perror(
"ExternalPipe()" );
66 result = mkfifo( fifo_name_2.c_str(), 0644 );
68 SG_LOG( SG_IO, SG_ALERT,
"Unable to create named pipe: "
70 perror(
"ExternalPipe()" );
73 pd1 = fopen( fifo_name_1.c_str(),
"w" );
75 SG_LOG( SG_IO, SG_ALERT,
"Unable to open named pipe: " << fifo_name_1 );
78 pd2 = fopen( fifo_name_2.c_str(),
"r" );
80 SG_LOG( SG_IO, SG_ALERT,
"Unable to open named pipe: " << fifo_name_2 );
87 if ( _protocol !=
"binary" && _protocol !=
"property" ) {
88 SG_LOG( SG_IO, SG_ALERT,
"Constructor(): Unknown ExternalPipe protocol."
89 <<
" Must be 'binary' or 'property'."
90 <<
" (assuming binary)" );
99 SG_LOG( SG_IO, SG_INFO,
"Closing up the ExternalPipe." );
104 result = fclose( pd1 );
106 SG_LOG( SG_IO, SG_ALERT,
"Unable to close named pipe: "
108 perror(
"~FGExternalPipe()" );
110 result = fclose( pd2 );
112 SG_LOG( SG_IO, SG_ALERT,
"Unable to close named pipe: "
114 perror(
"~FGExternalPipe()" );
120static int write_binary(
char cmd_type, FILE *pd,
char *cmd,
int len ) {
122 char *buf =
new char[len + 3];
125 unsigned char hi = (len + 1) / 256;
126 unsigned char lo = (len + 1) - (hi * 256);
135 memcpy( buf + 3, cmd, len );
137 if ( cmd_type ==
'1' ) {
139 cout << (int)hi <<
" ";
140 cout << (int)lo <<
" '";
141 for (
int i = 2;
i < len + 3; ++
i ) {
144 cout <<
"' (" << cmd <<
")" << endl;
145 }
else if ( cmd_type ==
'2' ) {
148 cout <<
"writing unknown command?" << endl;
156 int result = fwrite( buf, len + 3, 1, pd );
158 perror(
"write_binary()" );
159 SG_LOG( SG_IO, SG_ALERT,
"Write error to named pipe: " << pd );
175 int len = strlen(cmd);
176 char *buf =
new char[len + 1];
178 memcpy( buf, cmd, len );
181 int result = fwrite( buf, len + 1, 1, pd );
182 if ( result == len + 1 ) {
183 perror(
"write_property()" );
184 SG_LOG( SG_IO, SG_ALERT,
"Write error to named pipe: " << pd );
204 if ( _protocol ==
"binary" ) {
206 }
else if ( _protocol ==
"property" ) {
209 SG_LOG( SG_IO, SG_ALERT,
"Init(): Unknown ExternalPipe protocol."
210 <<
" Must be 'binary' or 'property'."
211 <<
" (assuming binary)" );
219void FGExternalPipe::init_binary() {
220 cout <<
"init_binary()" << endl;
222 double lon =
fgGetDouble(
"/sim/presets/longitude-deg" );
223 double lat =
fgGetDouble(
"/sim/presets/latitude-deg" );
224 double alt =
fgGetDouble(
"/sim/presets/altitude-ft" );
226 double heading =
fgGetDouble(
"/sim/presets/heading-deg");
227 double speed =
fgGetDouble(
"/sim/presets/airspeed-kt" );
228 double weight =
fgGetDouble(
"/sim/aircraft-weight-lbs" );
229 double cg_offset =
fgGetDouble(
"/sim/aircraft-cg-offset-inches" );
234 snprintf(cmd, 256,
"longitude-deg=%.8f", lon);
237 snprintf(cmd, 256,
"latitude-deg=%.8f", lat);
240 snprintf(cmd, 256,
"altitude-ft=%.8f", alt);
243 snprintf(cmd, 256,
"ground-m=%.8f", ground);
246 snprintf(cmd, 256,
"speed-kts=%.8f", speed);
249 snprintf(cmd, 256,
"heading-deg=%.8f", heading);
252 if ( weight > 1000.0 ) {
253 snprintf(cmd, 256,
"aircraft-weight-lbs=%.2f", weight);
256 last_weight = weight;
258 if ( cg_offset > -5.0 || cg_offset < 5.0 ) {
259 snprintf(cmd, 256,
"aircraft-cg-offset-inches=%.2f", cg_offset);
262 last_cg_offset = cg_offset;
264 SG_LOG( SG_IO, SG_ALERT,
"before sending reset command." );
266 if(
fgGetBool(
"/sim/presets/onground") ) {
267 snprintf(cmd, 256,
"reset=ground");
269 snprintf(cmd, 256,
"reset=air");
275 SG_LOG( SG_IO, SG_ALERT,
"Remote FDM init() finished." );
284void FGExternalPipe::init_property() {
285 cout <<
"init_property()" << endl;
287 double lon =
fgGetDouble(
"/sim/presets/longitude-deg" );
288 double lat =
fgGetDouble(
"/sim/presets/latitude-deg" );
289 double alt =
fgGetDouble(
"/sim/presets/altitude-ft" );
291 double heading =
fgGetDouble(
"/sim/presets/heading-deg");
292 double speed =
fgGetDouble(
"/sim/presets/airspeed-kt" );
293 double weight =
fgGetDouble(
"/sim/aircraft-weight-lbs" );
294 double cg_offset =
fgGetDouble(
"/sim/aircraft-cg-offset-inches" );
299 snprintf(cmd, 256,
"init longitude-deg=%.8f", lon);
302 snprintf(cmd, 256,
"init latitude-deg=%.8f", lat);
305 snprintf(cmd, 256,
"init altitude-ft=%.8f", alt);
308 snprintf(cmd, 256,
"init ground-m=%.8f", ground);
311 snprintf(cmd, 256,
"init speed-kts=%.8f", speed);
314 snprintf(cmd, 256,
"init heading-deg=%.8f", heading);
317 if ( weight > 1000.0 ) {
318 snprintf(cmd, 256,
"init aircraft-weight-lbs=%.2f", weight);
321 last_weight = weight;
323 if ( cg_offset > -5.0 || cg_offset < 5.0 ) {
324 snprintf(cmd, 256,
"init aircraft-cg-offset-inches=%.2f", cg_offset);
327 last_cg_offset = cg_offset;
329 SG_LOG( SG_IO, SG_ALERT,
"before sending reset command." );
331 if(
fgGetBool(
"/sim/presets/onground") ) {
332 snprintf(cmd, 256,
"reset ground");
334 snprintf(cmd, 256,
"reset air");
340 SG_LOG( SG_IO, SG_ALERT,
"Remote FDM init() finished." );
349 if ( _protocol ==
"binary" ) {
351 }
else if ( _protocol ==
"property" ) {
354 SG_LOG( SG_IO, SG_ALERT,
"Init(): Unknown ExternalPipe protocol."
355 <<
" Must be 'binary' or 'property'."
356 <<
" (assuming binary)" );
362void FGExternalPipe::update_binary(
double dt ) {
364 SG_LOG( SG_IO, SG_INFO,
"Start FGExternalPipe::udpate_binary()" );
369 if ( is_suspended() ) {
375 double weight =
fgGetDouble(
"/sim/aircraft-weight-lbs" );
376 static double last_weight = 0.0;
377 if ( fabs( weight - last_weight ) > 0.01 ) {
379 snprintf(cmd, 256,
"aircraft-weight-lbs=%.2f", weight);
382 last_weight = weight;
384 double cg_offset =
fgGetDouble(
"/sim/aircraft-cg-offset-inches" );
385 if ( fabs( cg_offset - last_cg_offset ) > 0.01 ) {
387 snprintf(cmd, 256,
"aircraft-cg-offset-inches=%.2f", cg_offset);
390 last_cg_offset = cg_offset;
393 length =
sizeof(ctrls);
396 *((
int *)ptr) = iterations;
399 memcpy( ptr, (
char *)(&ctrls), length );
403 result =
write_binary(
'2', pd1, buf, length +
sizeof(
int) );
407 length =
sizeof(fdm);
409 result = fread( (
char *)(& fdm), length, 1, pd2 );
411 SG_LOG( SG_IO, SG_ALERT,
"Read error from named pipe: "
412 << fifo_name_2 <<
" expected 1 item, but got " << result );
423void FGExternalPipe::process_set_command(
const string_list &tokens ) {
424 if ( tokens[1] ==
"geodetic_position" ) {
425 double lat_rad =
atof( tokens[2].c_str() );
426 double lon_rad =
atof( tokens[3].c_str() );
427 double alt_m =
atof( tokens[4].c_str() );
429 alt_m * SG_METER_TO_FEET );
433 }
else if ( tokens[1] ==
"euler_angles" ) {
434 double phi_rad =
atof( tokens[2].c_str() );
435 double theta_rad =
atof( tokens[3].c_str() );
436 double psi_rad =
atof( tokens[4].c_str() );
438 }
else if ( tokens[1] ==
"euler_rates" ) {
439 double phidot =
atof( tokens[2].c_str() );
440 double thetadot =
atof( tokens[3].c_str() );
441 double psidot =
atof( tokens[4].c_str() );
443 }
else if ( tokens[1] ==
"ned" ) {
444 double north_fps =
atof( tokens[2].c_str() );
445 double east_fps =
atof( tokens[3].c_str() );
446 double down_fps =
atof( tokens[4].c_str() );
448 }
else if ( tokens[1] ==
"alpha" ) {
450 }
else if ( tokens[1] ==
"beta" ) {
468 fgSetString( tokens[1].c_str(), tokens[2].c_str() );
474void FGExternalPipe::update_property(
double dt ) {
483 if ( is_suspended() ) {
489 double weight =
fgGetDouble(
"/sim/aircraft-weight-lbs" );
490 static double last_weight = 0.0;
491 if ( fabs( weight - last_weight ) > 0.01 ) {
492 snprintf(cmd, 256,
"init aircraft-weight-lbs=%.2f", weight);
495 last_weight = weight;
497 double cg_offset =
fgGetDouble(
"/sim/aircraft-cg-offset-inches" );
498 if ( fabs( cg_offset - last_cg_offset ) > 0.01 ) {
499 snprintf(cmd, 256,
"init aircraft-cg-offset-inches=%.2f", cg_offset);
502 last_cg_offset = cg_offset;
505 for (
unsigned int i = 0;
i < nodes.size();
i++ ) {
506 snprintf(cmd, 256,
"set %s %s", property_names[
i].c_str(),
512 snprintf(cmd, 256,
"update %d", iterations);
521 if ( fgets( cmd, 256, pd2 ) == NULL ) {
522 cout <<
"Error reading data" << endl;
529 cmd[strlen(cmd)-1] =
'\0';
532 string_list tokens = simgear::strutils::split( cmd,
" " );
534 if ( tokens[0] ==
"request" ) {
536 property_names.push_back( tokens[1] );
539 SGPropertyNode *node =
fgGetNode( tokens[1].c_str() );
540 if ( node == NULL ) {
542 node =
fgGetNode( tokens[1].c_str(),
true );
543 if ( tokens[2] ==
"bool" ) {
544 node->setBoolValue(
false);
545 }
else if ( tokens[2] ==
"int" ) {
546 node->setIntValue(0);
547 }
else if ( tokens[2] ==
"double" ) {
548 node->setDoubleValue(0.0);
549 }
else if ( tokens[2] ==
"string" ) {
550 node->setStringValue(
"");
552 cout <<
"Unknown data type: " << tokens[2]
553 <<
" for " << tokens[1] << endl;
556 nodes.push_back( node );
557 }
else if ( tokens[0] ==
"set" ) {
558 process_set_command( tokens );
559 }
else if ( tokens[0] ==
"update" ) {
562 cout <<
"unknown command = " << cmd << endl;
573SGSubsystemMgr::Registrant<FGExternalPipe> registrantFGExternalPipe;
static int write_binary(char cmd_type, FILE *pd, char *cmd, int len)
static int write_property(FILE *pd, char *cmd)
FGExternalPipe(double dt, std::string fifo_name, std::string protocol)
void update(double dt) override
SGPropertyNode * get_props()
void _set_Velocities_Local(double north, double east, double down)
void _set_Accels_Pilot_Body(double x, double y, double z)
void _set_Alpha(double a)
void _set_Velocities_Body(double u, double v, double w)
void _set_Climb_Rate(double rate)
void common_init()
Initialize the state of the FDM.
double get_Runway_altitude_m() const
void _set_V_calibrated_kts(double kts)
void _set_Altitude_AGL(double agl)
void _updateGeodeticPosition(double lat, double lon, double alt)
void _set_Euler_Rates(double phi, double theta, double psi)
int _calc_multiloop(double dt)
void _set_Euler_Angles(double phi, double theta, double psi)
std::vector< std::string > string_list
const std::string & getStringValue(const char *spec)
void FGProps2Ctrls< FGNetCtrls >(SGPropertyNode *props, FGNetCtrls *net, bool honor_freezes, bool net_byte_order)
void FGFDM2Props< FGNetFDM >(SGPropertyNode *props, FGNetFDM *net, bool net_byte_order)
static double atof(const string &str)
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.
bool fgSetString(char const *name, char const *str)
Set a string value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.