]> git.mxchange.org Git - flightgear.git/blob - src/FDM/LaRCsim/ls_geodesy.c
6d4073c8b786b46338aa13f3e59ff83609b509f9
[flightgear.git] / src / FDM / LaRCsim / ls_geodesy.c
1 /***************************************************************************
2
3         TITLE:  ls_geodesy
4         
5 ----------------------------------------------------------------------------
6
7         FUNCTION:       Converts geocentric coordinates to geodetic positions
8
9 ----------------------------------------------------------------------------
10
11         MODULE STATUS:  developmental
12
13 ----------------------------------------------------------------------------
14
15         GENEALOGY:      Written as part of LaRCSim project by E. B. Jackson
16
17 ----------------------------------------------------------------------------
18
19         DESIGNED BY:    E. B. Jackson
20         
21         CODED BY:       E. B. Jackson
22         
23         MAINTAINED BY:  E. B. Jackson
24
25 ----------------------------------------------------------------------------
26
27         MODIFICATION HISTORY:
28         
29         DATE    PURPOSE                                         BY
30         
31         930208  Modified to avoid singularity near polar region.        EBJ
32         930602  Moved backwards calcs here from ls_step.                EBJ
33         931214  Changed erroneous Latitude and Altitude variables to 
34                 *lat_geod and *alt in routine ls_geoc_to_geod.          EBJ
35         940111  Changed header files from old ls_eom.h style to ls_types, 
36                 and ls_constants.  Also replaced old DATA type with new
37                 SCALAR type.                                            EBJ
38
39         CURRENT RCS HEADER:
40
41 $Header$
42 $Log$
43 Revision 1.1  1999/04/05 21:32:45  curt
44 Initial revision
45
46 Revision 1.3  1998/07/08 14:41:37  curt
47 .
48
49 Revision 1.2  1998/01/19 18:40:25  curt
50 Tons of little changes to clean up the code and to remove fatal errors
51 when building with the c++ compiler.
52
53 Revision 1.1  1997/05/29 00:09:56  curt
54 Initial Flight Gear revision.
55
56  * Revision 1.5  1994/01/11  18:47:05  bjax
57  * Changed include files to use types and constants, not ls_eom.h
58  * Also changed DATA type to SCALAR type.
59  *
60  * Revision 1.4  1993/12/14  21:06:47  bjax
61  * Removed global variable references Altitude and Latitude.   EBJ
62  *
63  * Revision 1.3  1993/06/02  15:03:40  bjax
64  * Made new subroutine for calculating geodetic to geocentric; changed name
65  * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
66  *
67
68 ----------------------------------------------------------------------------
69
70         REFERENCES:
71
72                 [ 1]    Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
73                         Control and Simulation", Wiley and Sons, 1992.
74                         ISBN 0-471-61397-5                    
75
76
77 ----------------------------------------------------------------------------
78
79         CALLED BY:      ls_aux
80
81 ----------------------------------------------------------------------------
82
83         CALLS TO:
84
85 ----------------------------------------------------------------------------
86
87         INPUTS: 
88                 lat_geoc        Geocentric latitude, radians, + = North
89                 radius          C.G. radius to earth center, ft
90
91 ----------------------------------------------------------------------------
92
93         OUTPUTS:
94                 lat_geod        Geodetic latitude, radians, + = North
95                 alt             C.G. altitude above mean sea level, ft
96                 sea_level_r     radius from earth center to sea level at
97                                 local vertical (surface normal) of C.G.
98
99 --------------------------------------------------------------------------*/
100
101 #include "ls_types.h"
102 #include "ls_constants.h"
103 #include "ls_geodesy.h"
104 #include <math.h>
105
106 /* ONE_SECOND is pi/180/60/60, or about 100 feet at earths' equator */
107 #define ONE_SECOND 4.848136811E-6
108 #define HALF_PI 0.5*PI
109
110
111 void ls_geoc_to_geod( SCALAR lat_geoc, SCALAR radius, SCALAR *lat_geod, 
112                       SCALAR *alt, SCALAR *sea_level_r )
113 {
114         SCALAR  t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
115         SCALAR  sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
116
117         if(   ( (HALF_PI - lat_geoc) < ONE_SECOND )     /* near North pole */
118            || ( (HALF_PI + lat_geoc) < ONE_SECOND ) )   /* near South pole */
119           {
120             *lat_geod = lat_geoc;
121             *sea_level_r = EQUATORIAL_RADIUS*E;
122             *alt = radius - *sea_level_r;
123           }
124         else
125           {
126             t_lat = tan(lat_geoc);
127             x_alpha = E*EQUATORIAL_RADIUS/sqrt(t_lat*t_lat + E*E);
128             mu_alpha = atan2(sqrt(RESQ - x_alpha*x_alpha),E*x_alpha);
129             if (lat_geoc < 0) mu_alpha = - mu_alpha;
130             sin_mu_a = sin(mu_alpha);
131             delt_lambda = mu_alpha - lat_geoc;
132             r_alpha = x_alpha/cos(lat_geoc);
133             l_point = radius - r_alpha;
134             *alt = l_point*cos(delt_lambda);
135             denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
136             rho_alpha = EQUATORIAL_RADIUS*(1-EPS)/
137               (denom*denom*denom);
138             delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
139             *lat_geod = mu_alpha - delt_mu;
140             lambda_sl = atan( E*E * tan(*lat_geod) ); /* SL geoc. latitude */
141             sin_lambda_sl = sin( lambda_sl );
142             *sea_level_r = sqrt(RESQ
143                            /(1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
144           }
145 }
146
147
148 void ls_geod_to_geoc( SCALAR lat_geod, SCALAR alt, 
149                       SCALAR *sl_radius, SCALAR *lat_geoc )
150 {
151     SCALAR lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
152     
153     lambda_sl = atan( E*E * tan(lat_geod) ); /* sea level geocentric latitude */
154     sin_lambda_sl = sin( lambda_sl );
155     cos_lambda_sl = cos( lambda_sl );
156     sin_mu = sin(lat_geod);     /* Geodetic (map makers') latitude */
157     cos_mu = cos(lat_geod);
158     *sl_radius = sqrt(RESQ
159         /(1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
160     py = *sl_radius*sin_lambda_sl + alt*sin_mu;
161     px = *sl_radius*cos_lambda_sl + alt*cos_mu;
162     *lat_geoc = atan2( py, px );
163 }