]> git.mxchange.org Git - flightgear.git/blob - src/FDM/ExternalPipe/ExternalPipe.cxx
297fde2a68955f683508657f7c5bc01ddba3b9e4
[flightgear.git] / src / FDM / ExternalPipe / ExternalPipe.cxx
1 // ExternalPipe.cxx -- a "pipe" interface to an external flight dynamics model
2 //
3 // Written by Curtis Olson, started March 2003.
4 //
5 // Copyright (C) 2003  Curtis L. Olson  - curt@flightgear.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #ifdef HAVE_MKFIFO
28 #  include <sys/types.h>        // mkfifo() open() umask()
29 #  include <sys/stat.h>         // mkfifo() open() umask()
30 #  include <fcntl.h>            // open()
31 #  include <unistd.h>           // unlink()
32 #endif
33
34 #include <simgear/debug/logstream.hxx>
35 #include <simgear/io/lowlevel.hxx> // endian tests
36
37 #include <Main/fg_props.hxx>
38 #include <Network/native_ctrls.hxx>
39 #include <Network/native_fdm.hxx>
40
41 #include "ExternalPipe.hxx"
42
43
44 FGExternalPipe::FGExternalPipe( double dt, string name ) {
45     valid = true;
46     last_weight = 0.0;
47     last_cg_offset = -9999.9;
48
49     buf = new char[sizeof(char) + sizeof(int) + sizeof(ctrls)];
50
51 #ifdef HAVE_MKFIFO
52     fifo_name_1 = name + "1";
53     fifo_name_2 = name + "2";
54
55     SG_LOG( SG_IO, SG_ALERT, "ExternalPipe Inited with " << name );
56
57     // Make the named pipe
58     umask(0);
59     int result;
60     result = mkfifo( fifo_name_1.c_str(), 0644 );
61     if ( result == -1 ) {
62         SG_LOG( SG_IO, SG_ALERT, "Unable to create named pipe: "
63                 << fifo_name_1 );
64         valid = false;
65     }
66     result = mkfifo( fifo_name_2.c_str(), 0644 );
67     if ( result == -1 ) {
68         SG_LOG( SG_IO, SG_ALERT, "Unable to create named pipe: "
69                 << fifo_name_2 );
70         valid = false;
71     }
72
73     pd1 = open( fifo_name_1.c_str(), O_RDWR );
74     if ( pd1 == -1 ) {
75         SG_LOG( SG_IO, SG_ALERT, "Unable to open named pipe: " << fifo_name_1 );
76         valid = false;
77     }
78     pd2 = open( fifo_name_2.c_str(), O_RDWR );
79     if ( pd2 == -1 ) {
80         SG_LOG( SG_IO, SG_ALERT, "Unable to open named pipe: " << fifo_name_2 );
81         valid = false;
82     }
83 #endif
84 }
85
86
87 FGExternalPipe::~FGExternalPipe() {
88     delete [] buf;
89
90     SG_LOG( SG_IO, SG_INFO, "Closing up the ExternalPipe." );
91     
92 #ifdef HAVE_MKFIFO
93     // close
94     int result;
95     result = close( pd1 );
96     if ( result == -1 ) {
97         SG_LOG( SG_IO, SG_ALERT, "Unable to close named pipe: "
98                 << fifo_name_1 );
99     }
100     result = close( pd2 );
101     if ( result == -1 ) {
102         SG_LOG( SG_IO, SG_ALERT, "Unable to close named pipe: "
103                 << fifo_name_2 );
104     }
105 #endif
106 }
107
108
109 // Initialize the ExternalPipe flight model, dt is the time increment
110 // for each subsequent iteration through the EOM
111 void FGExternalPipe::init() {
112     // Explicitly call the superclass's
113     // init method first.
114     common_init();
115
116     double lon = fgGetDouble( "/sim/presets/longitude-deg" );
117     double lat = fgGetDouble( "/sim/presets/latitude-deg" );
118     double alt = fgGetDouble( "/sim/presets/altitude-ft" );
119     double ground = fgGetDouble( "/environment/ground-elevation-m" );
120     double heading = fgGetDouble("/sim/presets/heading-deg");
121     double speed = fgGetDouble( "/sim/presets/airspeed-kt" );
122     double weight = fgGetDouble( "/sim/aircraft-weight-lbs" );
123     double cg_offset = fgGetDouble( "/sim/aircraft-cg-offset-inches" );
124
125 #ifdef HAVE_MKFIFO
126
127     char cmd[256];
128     int result;
129
130     sprintf( cmd, "1longitude-deg=%.8f", lon );
131     result = write( pd1, cmd, strlen(cmd) );
132     if ( result == -1 ) {
133         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
134     }
135
136     sprintf( cmd, "1latitude-deg=%.8f", lat );
137     result = ::write( pd1, cmd, strlen(cmd) );
138     if ( result == -1 ) {
139         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
140     }
141
142     sprintf( cmd, "1altitude-ft=%.8f", alt );
143     result = write( pd1, cmd, strlen(cmd) );
144     if ( result == -1 ) {
145         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
146     }
147
148     sprintf( cmd, "1ground-m=%.8f", ground );
149     result = write( pd1, cmd, strlen(cmd) );
150     if ( result == -1 ) {
151         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
152     }
153
154     sprintf( cmd, "1speed-kts=%.8f", speed );
155     result = write( pd1, cmd, strlen(cmd) );
156     if ( result == -1 ) {
157         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
158     }
159
160     sprintf( cmd, "1heading-deg=%.8f", heading );
161     result = write( pd1, cmd, strlen(cmd) );
162     if ( result == -1 ) {
163         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
164     }
165
166     if ( weight > 1000.0 ) {
167       sprintf( cmd, "1aircraft-weight-lbs=%.2f", weight );
168       result = write( pd1, cmd, strlen(cmd) );
169       if ( result == -1 ) {
170         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
171       }
172     }
173     last_weight = weight;
174
175     if ( cg_offset > -5.0 || cg_offset < 5.0 ) {
176       sprintf( cmd, "1aircraft-cg-offset-inches=%.2f", cg_offset );
177       result = write( pd1, cmd, strlen(cmd) );
178       if ( result == -1 ) {
179         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
180       }
181     }
182     last_cg_offset = cg_offset;
183
184     SG_LOG( SG_IO, SG_INFO, "before sending reset command." );
185
186     if( fgGetBool("/sim/presets/onground") ) {
187       sprintf( cmd, "1reset=ground" );
188     } else {
189       sprintf( cmd, "1reset=air" );
190     }
191     result = write( pd1, cmd, strlen(cmd) );
192     if ( result == -1 ) {
193         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
194     }
195
196     SG_LOG( SG_IO, SG_INFO, "Remote FDM init() finished." );
197 #endif
198 }
199
200
201 // Run an iteration of the EOM.
202 void FGExternalPipe::update( double dt ) {
203 #ifdef HAVE_MKFIFO
204     // SG_LOG( SG_IO, SG_INFO, "Start FGExternalPipe::udpate()" );
205
206     int length;
207     int result;
208     
209     if ( is_suspended() ) {
210         return;
211     }
212
213     int iterations = _calc_multiloop(dt);
214
215     double weight = fgGetDouble( "/sim/aircraft-weight-lbs" );
216     static double last_weight = 0.0;
217     if ( fabs( weight - last_weight ) > 0.01 ) {
218       char cmd[256];
219       sprintf( cmd, "1aircraft-weight-lbs=%.2f", weight );
220       result = write( pd1, cmd, strlen(cmd) );
221       if ( result == -1 ) {
222         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
223       }
224     }
225     last_weight = weight;
226
227     double cg_offset = fgGetDouble( "/sim/aircraft-cg-offset-inches" );
228     if ( fabs( cg_offset - last_cg_offset ) > 0.01 ) {
229       char cmd[256];
230       sprintf( cmd, "1aircraft-cg-offset-inches=%.2f", cg_offset );
231       result = write( pd1, cmd, strlen(cmd) );
232       if ( result == -1 ) {
233         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: " << fifo_name_1 );
234       }
235     }
236     last_cg_offset = cg_offset;
237
238     // Send control positions to remote fdm
239     length = sizeof(ctrls);
240     FGProps2NetCtrls( &ctrls, true, false );
241     char *ptr = buf;
242     *ptr = '2';
243     ptr++;
244     *((int *)ptr) = iterations;
245     ptr += sizeof(int);
246     memcpy( ptr, (char *)(&ctrls), length );
247     cout << "writing control structure to remote fdm." << endl;
248     result = write( pd1, buf, length + 1 );
249     if ( result == -1 ) {
250         SG_LOG( SG_IO, SG_ALERT, "Write error to named pipe: "
251                 << fifo_name_1 );
252     } else {
253         cout << "  write successful = " << length + 1 << endl;
254     }
255
256     // Read fdm values
257     length = sizeof(fdm);
258     cout << "about to read fdm data from remote fdm." << endl;
259     result = read( pd2, (char *)(& fdm), length );
260     if ( result == -1 ) {
261         SG_LOG( SG_IO, SG_ALERT, "Read error from named pipe: "
262                 << fifo_name_2 );
263     } else {
264         cout << "  read successful." << endl;
265     }
266     FGNetFDM2Props( &fdm, false );
267 #endif
268 }