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