]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/steam.cxx
8ec8f211e09c078ffa88e715d029b92cbdcd5d68
[flightgear.git] / src / Cockpit / steam.cxx
1 // steam.cxx - Steam Gauge Calculations
2 //
3 // Copyright (C) 2000  Alexander Perry - alex.perry@ieee.org
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 // $Id$
20
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #if defined( FG_HAVE_NATIVE_SGI_COMPILERS )
27 #  include <iostream.h>
28 #else
29 #  include <iostream>
30 #endif
31
32 #include <simgear/constants.h>
33 #include <simgear/math/fg_types.hxx>
34 #include <Main/options.hxx>
35 #include <Main/bfi.hxx>
36
37 FG_USING_NAMESPACE(std);
38
39 #include "radiostack.hxx"
40 #include "steam.hxx"
41
42
43 \f
44 ////////////////////////////////////////////////////////////////////////
45 // Declare the functions that read the variables
46 ////////////////////////////////////////////////////////////////////////
47
48 // Anything that reads the BFI directly is not implemented at all!
49
50
51 #define VARY_E          (14)
52
53
54 double FGSteam::the_STATIC_inhg = 29.92;
55 double FGSteam::the_ALT_ft = 0.0;
56 double FGSteam::get_ALT_ft() { _CatchUp(); return the_ALT_ft; }
57
58 double FGSteam::get_ASI_kias() { return FGBFI::getAirspeed(); }
59
60 double FGSteam::the_VSI_case = 29.92;
61 double FGSteam::the_VSI_fps = 0.0;
62 double FGSteam::get_VSI_fps() { _CatchUp(); return the_VSI_fps; }
63
64 double FGSteam::the_VACUUM_inhg = 0.0;
65 double FGSteam::get_VACUUM_inhg() { _CatchUp(); return the_VACUUM_inhg; }
66
67 double FGSteam::get_MH_deg () {
68     return FGBFI::getHeading () - FGBFI::getMagVar ();
69 }
70 double FGSteam::get_DG_deg () {
71     return FGBFI::getHeading () - FGBFI::getMagVar ();
72 }
73
74 double FGSteam::get_TC_rad   () { return FGBFI::getSideSlip (); }
75 double FGSteam::get_TC_radps () { return FGBFI::getRoll (); }
76
77 \f
78 ////////////////////////////////////////////////////////////////////////
79 // Recording the current time
80 ////////////////////////////////////////////////////////////////////////
81
82
83 int FGSteam::_UpdatesPending = 9999;  /* Forces filter to reset */
84
85
86 void FGSteam::update ( int timesteps )
87 {
88         _UpdatesPending += timesteps;
89 }
90
91
92 void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
93 {
94         if ( tc < 0.0 )
95         {       if ( tc < -1.0 )
96                 {       /* time went backwards; kill the filter */
97                         (*outthe) = inthe;
98                 } else
99                 {       /* ignore mildly negative time */
100                 }
101         } else
102         if ( tc < 0.2 )
103         {       /* Normal mode of operation */
104                 (*outthe) = (*outthe) * ( 1.0 - tc )
105                           +    inthe  * tc;
106         } else
107         if ( tc > 5.0 )
108         {       /* Huge time step; assume filter has settled */
109                 (*outthe) = inthe;
110         } else
111         {       /* Moderate time step; non linear response */
112                 double keep = exp ( -tc );
113                 // printf ( "ARP: Keep is %f\n", keep );
114                 (*outthe) = (*outthe) * keep
115                           +    inthe  * ( 1.0 - keep );
116         }
117 }
118
119
120 \f
121 ////////////////////////////////////////////////////////////////////////
122 // Here the fun really begins
123 ////////////////////////////////////////////////////////////////////////
124
125
126 void FGSteam::_CatchUp()
127 { if ( _UpdatesPending != 0 )
128   {     double dt = _UpdatesPending * 1.0 / current_options.get_model_hz();
129         int i,j;
130         double d, the_ENGINE_rpm;
131         /*
132         Someone has called our update function and
133         it turns out that we are running somewhat behind.
134         Here, we recalculate everything for a 'dt' second step.
135         */
136
137         /**************************
138         This is not actually correct, but provides a
139         scaling capability for the vacuum pump later on.
140         When we have a real engine model, we can ask it.
141         */
142         the_ENGINE_rpm = FGBFI::getThrottle() * 26.0;
143
144         /**************************
145         This is just temporary, until the static source works,
146         so we just filter the actual value by one second to
147         account for the line impedance of the plumbing.
148         */
149         set_lowpass ( & the_ALT_ft, FGBFI::getAltitude(), dt );
150
151         /**************************
152         First, we need to know what the static line is reporting,
153         which is a whole simulation area in itself.  For now, we cheat.
154         */
155         the_STATIC_inhg = 29.92; 
156         i = (int) the_ALT_ft;
157         while ( i > 9000 )
158         {       the_STATIC_inhg *= 0.707;
159                 i -= 9000;
160         }
161         the_STATIC_inhg *= ( 1.0 - 0.293 * i / 9000.0 );
162
163         /*
164         NO alternate static source error (student feature), 
165         NO possibility of blockage (instructor feature),
166         NO slip-induced error, important for C172 for example.
167         */
168
169         /**************************
170         The VSI case is a low-pass filter of the static line pressure.
171         The instrument reports the difference, scaled to approx ft.
172         NO option for student to break glass when static source fails.
173         NO capability for a fixed non-zero reading when level.
174         NO capability to have a scaling error of maybe a factor of two.
175         */
176         the_VSI_fps = ( the_VSI_case - the_STATIC_inhg )
177                     * 10000.0; /* manual scaling factor */      
178         set_lowpass ( & the_VSI_case, the_STATIC_inhg, dt/6.0 );
179
180         /**************************
181         The engine driven vacuum pump is directly attached
182         to the engine shaft, so each engine rotation pumps
183         a fixed volume.  The amount of air in that volume
184         is determined by the vacuum line's internal pressure.
185         The instruments are essentially leaking air like
186         a fixed source impedance from atmospheric pressure.
187         The regulator provides a digital limit setting,
188         which is open circuit unless the pressure drop is big.
189         Thus, we can compute the vacuum line pressure directly.
190         We assume that there is negligible reservoir space.
191         NO failure of the pump supported (yet)
192         */
193         the_VACUUM_inhg = the_STATIC_inhg *
194                 the_ENGINE_rpm / ( the_ENGINE_rpm + 10000.0 );
195         if ( the_VACUUM_inhg > 5.0 )
196              the_VACUUM_inhg = 5.0;
197
198 /*
199 > I was merely going to do the engine rpm driven vacuum pump for both
200 > the AI and DG, have the gyros spin down down in power off descents, 
201 > have it tumble when you exceed the usual pitch or bank limits,
202 > put in those insidious turning errors ... for now anyway.
203 */
204
205         /**************************
206         Finished updates, now clear the timer 
207         */
208         _UpdatesPending = 0;
209   }
210 }
211
212 \f
213 ////////////////////////////////////////////////////////////////////////
214 // Everything below is a transient hack; expect it to disappear
215 ////////////////////////////////////////////////////////////////////////
216
217 /* KMYF ILS */
218 #define NAV1_LOC        (1)
219 #define NAV1_Lat        (  32.0 + 48.94/60.0)
220 #define NAV1_Lon        (-117.0 - 08.37/60.0)
221 #define NAV1_Rad        280.0
222 #define NAV1_Alt        423
223
224 /* MZB stepdown radial */
225 #define NAV2_Lat        (  32.0 + 46.93/60.0)
226 #define NAV2_Lon        (-117.0 - 13.53/60.0)
227 #define NAV2_Rad        068.0
228
229 /* HAILE intersection */
230 #define ADF_Lat         (  32.0 + 46.79/60.0)
231 #define ADF_Lon         (-117.0 - 02.70/60.0)
232
233
234
235 double FGSteam::get_HackGS_deg   ()
236 {       double x,y,dme;
237         if (0==NAV1_LOC) return 0.0;
238         y = 60.0 * ( NAV1_Lat - FGBFI::getLatitude () );
239         x = 60.0 * ( NAV1_Lon - FGBFI::getLongitude() )
240                         * cos ( FGBFI::getLatitude () / RAD_TO_DEG );
241         dme = x*x + y*y;
242         if ( dme > 0.1 ) x = sqrt ( dme ); else x = 0.3;
243         y = FGBFI::getAltitude() - NAV1_Alt;
244         return 3.0 - (y/x) * 60.0 / 6000.0;
245 }
246
247
248 double FGSteam::get_HackVOR1_deg ()
249 {       double r;
250         double x,y;
251         y = 60.0 * ( NAV1_Lat - FGBFI::getLatitude () );
252         x = 60.0 * ( NAV1_Lon - FGBFI::getLongitude() )
253                         * cos ( FGBFI::getLatitude () / RAD_TO_DEG );
254         r = atan2 ( x, y ) * RAD_TO_DEG - NAV1_Rad - FGBFI::getMagVar();
255         if (r> 180.0) r-=360.0; else
256         if (r<-180.0) r+=360.0;
257         if ( fabs(r) > 90.0 )
258                 r = ( r<0.0 ? -r-180.0 : -r+180.0 );
259         if (NAV1_LOC) r*=5.0;
260         return r;
261 }
262
263
264 double FGSteam::get_HackVOR2_deg ()
265 {       double r;
266         double x,y;
267         y = 60.0 * ( NAV2_Lat - FGBFI::getLatitude () );
268         x = 60.0 * ( NAV2_Lon - FGBFI::getLongitude() )
269                         * cos ( FGBFI::getLatitude () / RAD_TO_DEG );
270         r = atan2 ( x, y ) * RAD_TO_DEG - NAV2_Rad - FGBFI::getMagVar();
271         if (r> 180.0) r-=360.0; else
272         if (r<-180.0) r+=360.0;
273         if ( fabs(r) > 90.0 )
274                 r = ( r<0.0 ? -r-180.0 : -r+180.0 );
275         return r;
276 }
277
278
279 double FGSteam::get_HackOBS1_deg ()
280 {       return  NAV1_Rad; 
281 }
282
283
284 double FGSteam::get_HackOBS2_deg ()
285 {       return  NAV2_Rad; 
286 }
287
288
289 double FGSteam::get_HackADF_deg ()
290 {       double r;
291         double x,y;
292         y = 60.0 * ( ADF_Lat - FGBFI::getLatitude () );
293         x = 60.0 * ( ADF_Lon - FGBFI::getLongitude() )
294                        * cos ( FGBFI::getLatitude () / RAD_TO_DEG );
295         r = atan2 ( x, y ) * RAD_TO_DEG - FGBFI::getHeading ();
296         return r;
297 }
298
299
300 // end of steam.cxx