|
ocssw
1.0
|
00001 /* 00002 *---------------------------------------------------------------------- 00003 * @(#) ctotc.c 1.0 20 Mar 93 <shc> 00004 * Copyright (c) 1993, CSIRO Division of Oceanography. 00005 *---------------------------------------------------------------------- 00006 * 00007 * ctotc -- 00008 * 00009 * Rectangular (Cartesian) to topocentric coordinate conversion. 00010 * 00011 * Results: 00012 * 00013 * Given the rectangular (Cartesian) earth-centred coordinates of an 00014 * object, the latitude, longitude and height above the geoid of 00015 * an observer and the Greenwich Hour angle, calculate the topocentric 00016 * coordinates of the object (azimuth, elevation and range) and, 00017 * optionally, derivatives of these wrt Cartesian. 00018 * Units are radians, metres and seconds. 00019 * 00020 * Azimuth, elevation and range are returned in TOP. If "DAER" 00021 * is non-NULL, the 3x3 Jacobian of topocentric coordinates wrt 00022 * rectangular coordinates is returned in DAER. 00023 * 00024 * Side effects: 00025 * None. 00026 * 00027 * History: 00028 * 17 Dec 90 <shc> 00029 * Initial version 00030 * 00031 * 23 Jan 91 <shc> 00032 * Reduced number of trig routine calls 00033 * 00034 * 20 Mar 93 <shc> 00035 * Converted from FORTRAN to C 00036 * 00037 *---------------------------------------------------------------------- 00038 */ 00039 00040 #include "orbit.h" 00041 00042 00043 void 00044 ctotc(r, obs, gha, top, daer) 00045 double r[3]; /* Rectangular coordinates of object (metres) */ 00046 struct GEODETIC *obs; /* Observer's lat, lon (radians) and height (m) */ 00047 double gha; /* Greenwich hour angle (radians) */ 00048 struct TOPOCENTRIC *top; /* Resulting az, el and range */ 00049 double daer[3][3]; /* Jacobian of (az,el,range) wrt (x,y,z) */ 00050 { 00051 int i, j; 00052 double olat, olon, ohgt, clat, clon, slat, slon; 00053 double ens, xo, yo, zo, xos, yos, zos, xlt, ylt, zlt; 00054 double rngsq, range; 00055 double emlt[3][3], dlt[3][3]; 00056 /* 00057 * Observer geodetic coordinates (latitude, longitude and height) in 00058 * radians and metres. 00059 */ 00060 olat = obs->lat; 00061 olon = AN2PI(obs->lon + gha); 00062 ohgt = obs->height; 00063 00064 clat = cos(olat); 00065 clon = cos(olon); 00066 slat = sin(olat); 00067 slon = sin(olon); 00068 /* 00069 * Rotation matrix to bring geocentric reference frame 00070 * parallel to local tangent reference frame. 00071 */ 00072 emlt[0][0] = - slon; 00073 emlt[0][1] = clon; 00074 emlt[0][2] = 0.0; 00075 emlt[1][0] = - slat*clon; 00076 emlt[1][1] = - slat*slon; 00077 emlt[1][2] = clat; 00078 emlt[2][0] = clat*clon; 00079 emlt[2][1] = clat*slon; 00080 emlt[2][2] = slat; 00081 /* 00082 * Geocentric vector to observer 00083 */ 00084 ens = EQRAD / sqrt(1.0 - FLT*(2.0 - FLT)*slat*slat); 00085 xo = (ens + ohgt) * clat * clon; 00086 yo = (ens + ohgt) * clat * slon; 00087 zo = (ens*(1.0 - FLT)*(1.0 - FLT) + ohgt) * slat; 00088 /* 00089 * Vector from observer to object 00090 */ 00091 xos = r[0] - xo; 00092 yos = r[1] - yo; 00093 zos = r[2] - zo; 00094 /* 00095 * Position of object in local tangent reference frame 00096 */ 00097 xlt = emlt[0][0]*xos + emlt[0][1]*yos + emlt[0][2]*zos; 00098 ylt = emlt[1][0]*xos + emlt[1][1]*yos + emlt[1][2]*zos; 00099 zlt = emlt[2][0]*xos + emlt[2][1]*yos + emlt[2][2]*zos; 00100 /* 00101 * Spacecraft azimuth, elevation and range 00102 */ 00103 rngsq = xlt*xlt + ylt*ylt + zlt*zlt; 00104 range = sqrt(rngsq); 00105 top->az = AN2PI(atan2(xlt, ylt)); 00106 top->el = asin(zlt / range); 00107 top->range = range; 00108 /* 00109 * Optionally calculate derivatives of azimuth, elevation and range 00110 * with respect to the object rectangular coordinates. 00111 */ 00112 if (daer != NULL) { 00113 double a1, a2; 00114 /* 00115 * Derivatives of azimuth (DLT[0][*]), elevation (DLT[1][*]) and 00116 * range (DLT[2][*]) wrt object position in local tangent frame. 00117 */ 00118 a1 = xlt*xlt + ylt*ylt; 00119 a2 = sqrt(a1); 00120 dlt[0][0] = ylt / a1; 00121 dlt[0][1] = -xlt / a1; 00122 dlt[0][2] = 0.0; 00123 dlt[1][0] = -zlt*xlt / (rngsq * a2); 00124 dlt[1][1] = -zlt*ylt / (rngsq * a2); 00125 dlt[1][2] = a2 / rngsq; 00126 dlt[2][0] = xlt / range; 00127 dlt[2][1] = ylt / range; 00128 dlt[2][2] = zlt / range; 00129 /* 00130 * Convert derivatives wrt local tangent frame to derivatives wrt 00131 * geocentric reference frame: Product[dlt, emlt]. 00132 */ 00133 for (i = 0; i < 3; i++) { 00134 for (j = 0; j < 3; j++) { 00135 daer[i][j] = dlt[i][0]*emlt[0][j] + 00136 dlt[i][1]*emlt[1][j] + 00137 dlt[i][2]*emlt[2][j]; 00138 } 00139 } 00140 } 00141 00142 return; 00143 }
1.7.6.1