00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <math.h>
00014
00015 #include "linear_algebra.h"
00016 #include "coord_system.h"
00017
00057 void wgsllh2ecef(const double const llh[3], double ecef[3]) {
00058 double d = WGS84_E * sin(llh[0]);
00059 double N = WGS84_A / sqrt(1. - d*d);
00060
00061 ecef[0] = (N + llh[2]) * cos(llh[0]) * cos(llh[1]);
00062 ecef[1] = (N + llh[2]) * cos(llh[0]) * sin(llh[1]);
00063 ecef[2] = ((1 - WGS84_E*WGS84_E)*N + llh[2]) * sin(llh[0]);
00064 }
00065
00092 void wgsecef2llh(const double const ecef[3], double llh[3]) {
00093
00094 const double p = sqrt(ecef[0]*ecef[0] + ecef[1]*ecef[1]);
00095
00096
00097 if (p != 0)
00098 llh[1] = atan2(ecef[1], ecef[0]);
00099 else
00100 llh[1] = 0;
00101
00102
00103
00104 if (p < WGS84_A*1e-16) {
00105 llh[0] = copysign(M_PI_2, ecef[2]);
00106 llh[2] = fabs(ecef[2]) - WGS84_B;
00107 return;
00108 }
00109
00110
00111 const double P = p / WGS84_A;
00112 const double e_c = sqrt(1. - WGS84_E*WGS84_E);
00113 const double Z = fabs(ecef[2]) * e_c / WGS84_A;
00114
00115
00116 double S = Z;
00117 double C = e_c * P;
00118
00119
00120
00121 double prev_C = -1;
00122 double prev_S = -1;
00123
00124 double A_n, B_n, D_n, F_n;
00125
00126
00127
00128 for (int i=0; i<10; i++)
00129 {
00130
00131
00132 A_n = sqrt(S*S + C*C);
00133 D_n = Z*A_n*A_n*A_n + WGS84_E*WGS84_E*S*S*S;
00134 F_n = P*A_n*A_n*A_n - WGS84_E*WGS84_E*C*C*C;
00135 B_n = 1.5*WGS84_E*S*C*C*(A_n*(P*S - Z*C) - WGS84_E*S*C);
00136
00137
00138 S = D_n*F_n - B_n*S;
00139 C = F_n*F_n - B_n*C;
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 if (S > C) {
00163 C = C / S;
00164 S = 1;
00165 } else {
00166 S = S / C;
00167 C = 1;
00168 }
00169
00170
00171 if (fabs(S - prev_S) < 1e-16 && fabs(C - prev_C) < 1e-16) {
00172 break;
00173 } else {
00174 prev_S = S;
00175 prev_C = C;
00176 }
00177 }
00178
00179 A_n = sqrt(S*S + C*C);
00180 llh[0] = copysign(1.0, ecef[2]) * atan(S / (e_c*C));
00181 llh[2] = (p*e_c*C + fabs(ecef[2])*S - WGS84_A*e_c*A_n) / sqrt(e_c*e_c*C*C + S*S);
00182 }
00183
00192 static void ecef2ned_matrix(const double ref_ecef[3], double M[3][3]) {
00193 double hyp_az, hyp_el;
00194 double sin_el, cos_el, sin_az, cos_az;
00195
00196
00197 hyp_az = sqrt(ref_ecef[0]*ref_ecef[0] + ref_ecef[1]*ref_ecef[1]);
00198 hyp_el = sqrt(hyp_az*hyp_az + ref_ecef[2]*ref_ecef[2]);
00199 sin_el = ref_ecef[2] / hyp_el;
00200 cos_el = hyp_az / hyp_el;
00201 sin_az = ref_ecef[1] / hyp_az;
00202 cos_az = ref_ecef[0] / hyp_az;
00203
00204 M[0][0] = -sin_el * cos_az;
00205 M[0][1] = -sin_el * sin_az;
00206 M[0][2] = cos_el;
00207 M[1][0] = -sin_az;
00208 M[1][1] = cos_az;
00209 M[1][2] = 0.0;
00210 M[2][0] = -cos_el * cos_az;
00211 M[2][1] = -cos_el * sin_az;
00212 M[2][2] = -sin_el;
00213 }
00214
00215
00234 void wgsecef2ned(const double ecef[3], const double ref_ecef[3],
00235 double ned[3]) {
00236 double M[3][3];
00237
00238 ecef2ned_matrix(ref_ecef, M);
00239 matrix_multiply(3, 3, 1, (double *)M, ecef, ned);
00240 }
00241
00256 void wgsecef2ned_d(const double ecef[3], const double ref_ecef[3],
00257 double ned[3]) {
00258 double tempv[3];
00259 vector_subtract(3, ecef, ref_ecef, tempv);
00260 wgsecef2ned(tempv, ref_ecef, ned);
00261 }
00262
00263
00281 void wgsned2ecef(const double ned[3], const double ref_ecef[3],
00282 double ecef[3]) {
00283 double M[3][3], M_transpose[3][3];
00284 ecef2ned_matrix(ref_ecef, M);
00285 matrix_transpose(3, 3, (double *)M, (double *)M_transpose);
00286 matrix_multiply(3, 3, 1, (double *)M_transpose, ned, ecef);
00287 }
00288
00301 void wgsned2ecef_d(const double ned[3], const double ref_ecef[3],
00302 double ecef[3]) {
00303 double tempv[3];
00304 wgsned2ecef(ned, ref_ecef, tempv);
00305 vector_add(3, tempv, ref_ecef, ecef);
00306 }
00307
00308
00325 void wgsecef2azel(const double ecef[3], const double ref_ecef[3],
00326 double* azimuth, double* elevation) {
00327 double ned[3];
00328
00329
00330
00331 wgsecef2ned_d(ecef, ref_ecef, ned);
00332
00333 *azimuth = atan2(ned[1], ned[0]);
00334
00335
00336 if (*azimuth < 0)
00337 *azimuth += 2*M_PI;
00338
00339 *elevation = asin(-ned[2]/vector_norm(3, ned));
00340 }
00341