Due to the lapse in federal government funding, NASA is not updating this website. We sincerely regret this inconvenience.
NASA Logo
Ocean Color Science Software

ocssw V2022
ctotc.c
Go to the documentation of this file.
1 /*
2  *----------------------------------------------------------------------
3  * @(#) ctotc.c 1.0 20 Mar 93 <shc>
4  * Copyright (c) 1993, CSIRO Division of Oceanography.
5  *----------------------------------------------------------------------
6  *
7  * ctotc --
8  *
9  * Rectangular (Cartesian) to topocentric coordinate conversion.
10  *
11  * Results:
12  *
13  * Given the rectangular (Cartesian) earth-centred coordinates of an
14  * object, the latitude, longitude and height above the geoid of
15  * an observer and the Greenwich Hour angle, calculate the topocentric
16  * coordinates of the object (azimuth, elevation and range) and,
17  * optionally, derivatives of these wrt Cartesian.
18  * Units are radians, metres and seconds.
19  *
20  * Azimuth, elevation and range are returned in TOP. If "DAER"
21  * is non-NULL, the 3x3 Jacobian of topocentric coordinates wrt
22  * rectangular coordinates is returned in DAER.
23  *
24  * Side effects:
25  * None.
26  *
27  * History:
28  * 17 Dec 90 <shc>
29  * Initial version
30  *
31  * 23 Jan 91 <shc>
32  * Reduced number of trig routine calls
33  *
34  * 20 Mar 93 <shc>
35  * Converted from FORTRAN to C
36  *
37  *----------------------------------------------------------------------
38  */
39 
40 #include "orbit.h"
41 
42 void
43 ctotc(r, obs, gha, top, daer)
44 double r[3]; /* Rectangular coordinates of object (metres) */
45 struct GEODETIC *obs; /* Observer's lat, lon (radians) and height (m) */
46 double gha; /* Greenwich hour angle (radians) */
47 struct TOPOCENTRIC *top; /* Resulting az, el and range */
48 double daer[3][3]; /* Jacobian of (az,el,range) wrt (x,y,z) */
49 {
50  int i, j;
51  double olat, olon, ohgt, clat, clon, slat, slon;
52  double ens, xo, yo, zo, xos, yos, zos, xlt, ylt, zlt;
53  double rngsq, range;
54  double emlt[3][3], dlt[3][3];
55  /*
56  * Observer geodetic coordinates (latitude, longitude and height) in
57  * radians and metres.
58  */
59  olat = obs->lat;
60  olon = AN2PI(obs->lon + gha);
61  ohgt = obs->height;
62 
63  clat = cos(olat);
64  clon = cos(olon);
65  slat = sin(olat);
66  slon = sin(olon);
67  /*
68  * Rotation matrix to bring geocentric reference frame
69  * parallel to local tangent reference frame.
70  */
71  emlt[0][0] = -slon;
72  emlt[0][1] = clon;
73  emlt[0][2] = 0.0;
74  emlt[1][0] = -slat*clon;
75  emlt[1][1] = -slat*slon;
76  emlt[1][2] = clat;
77  emlt[2][0] = clat*clon;
78  emlt[2][1] = clat*slon;
79  emlt[2][2] = slat;
80  /*
81  * Geocentric vector to observer
82  */
83  ens = EQRAD / sqrt(1.0 - FLT * (2.0 - FLT) * slat * slat);
84  xo = (ens + ohgt) * clat * clon;
85  yo = (ens + ohgt) * clat * slon;
86  zo = (ens * (1.0 - FLT)*(1.0 - FLT) + ohgt) * slat;
87  /*
88  * Vector from observer to object
89  */
90  xos = r[0] - xo;
91  yos = r[1] - yo;
92  zos = r[2] - zo;
93  /*
94  * Position of object in local tangent reference frame
95  */
96  xlt = emlt[0][0] * xos + emlt[0][1] * yos + emlt[0][2] * zos;
97  ylt = emlt[1][0] * xos + emlt[1][1] * yos + emlt[1][2] * zos;
98  zlt = emlt[2][0] * xos + emlt[2][1] * yos + emlt[2][2] * zos;
99  /*
100  * Spacecraft azimuth, elevation and range
101  */
102  rngsq = xlt * xlt + ylt * ylt + zlt*zlt;
103  range = sqrt(rngsq);
104  top->az = AN2PI(atan2(xlt, ylt));
105  top->el = asin(zlt / range);
106  top->range = range;
107  /*
108  * Optionally calculate derivatives of azimuth, elevation and range
109  * with respect to the object rectangular coordinates.
110  */
111  if (daer != NULL) {
112  double a1, a2;
113  /*
114  * Derivatives of azimuth (DLT[0][*]), elevation (DLT[1][*]) and
115  * range (DLT[2][*]) wrt object position in local tangent frame.
116  */
117  a1 = xlt * xlt + ylt*ylt;
118  a2 = sqrt(a1);
119  dlt[0][0] = ylt / a1;
120  dlt[0][1] = -xlt / a1;
121  dlt[0][2] = 0.0;
122  dlt[1][0] = -zlt * xlt / (rngsq * a2);
123  dlt[1][1] = -zlt * ylt / (rngsq * a2);
124  dlt[1][2] = a2 / rngsq;
125  dlt[2][0] = xlt / range;
126  dlt[2][1] = ylt / range;
127  dlt[2][2] = zlt / range;
128  /*
129  * Convert derivatives wrt local tangent frame to derivatives wrt
130  * geocentric reference frame: Product[dlt, emlt].
131  */
132  for (i = 0; i < 3; i++) {
133  for (j = 0; j < 3; j++) {
134  daer[i][j] = dlt[i][0] * emlt[0][j] +
135  dlt[i][1] * emlt[1][j] +
136  dlt[i][2] * emlt[2][j];
137  }
138  }
139  }
140 
141  return;
142 }
int r
Definition: decode_rs.h:73
int j
Definition: decode_rs.h:73
#define EQRAD
Definition: earth.h:33
double height
Definition: orbit.h:119
#define NULL
Definition: decode_rs.h:63
void ctotc(r, struct GEODETIC *obs, double gha, struct TOPOCENTRIC *top, daer)
Definition: ctotc.c:43
double lon
Definition: orbit.h:118
#define AN2PI(X)
Definition: orbit.h:57
float dlt
Definition: atrem_cor.h:94
int i
Definition: decode_rs.h:71
#define FLT
Definition: earth.h:31
double lat
Definition: orbit.h:117