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