26 bool enu2lla(
double lla[3],
const double enu[3],
const double ref_lla[3]){
27 double ref_xyz[3],diff_xyz[3],xyz[3],R[3][3],Rt[3][3];
30 if (!lla2xyz(ref_xyz,ref_lla))
33 rot3d(R, ref_lla[0], ref_lla[1]);
35 transposeMatrix(Rt,R);
37 matrixMultiply(diff_xyz,Rt,enu);
39 xyz[0] = diff_xyz[0] + ref_xyz[0];
40 xyz[1] = diff_xyz[1] + ref_xyz[1];
41 xyz[2] = diff_xyz[2] + ref_xyz[2];
52 bool lla2enu(
double enu[3],
const double lla[3],
const double ref_lla[3]){
59 if(!xyz2enu(enu,xyz,ref_lla))
68 bool xyz2lla(
double lla[3],
const double xyz[3]){
73 double A_EARTH = 6378137.0;
74 double flattening = 1.0 / 298.257223563;
75 double NAV_E2 = (2.0 - flattening) * flattening;
76 double rad2deg = 180.0 / M_PI_R;
78 if ((xyz[0] == 0.0) & (xyz[1] == 0.0)) {
81 lla[1] = atan2(xyz[1], xyz[0]) * rad2deg;
84 if ((xyz[0] == 0.0) & (xyz[1] == 0.0) & (xyz[2] == 0.0)) {
85 std::cout <<
"WGS xyz at center of earth" << std::endl;
89 double rhosqrd = xyz[0] * xyz[0] + xyz[1] * xyz[1];
90 double rho = sqrt(rhosqrd);
91 double templat = atan2(xyz[2], rho);
92 double tempalt = sqrt(rhosqrd + xyz[2] * xyz[2]) - A_EARTH;
93 double rhoerror = 1000.0;
94 double zerror = 1000.0;
103 while ((abs(rhoerror) > 1e-6) | (abs(zerror) > 1e-6)) {
104 double slat = sin(templat);
105 double clat = cos(templat);
106 double q = 1.0 - NAV_E2 * slat*slat;
107 double r_n = A_EARTH / sqrt(q);
108 double drdl = r_n * NAV_E2 * slat * clat / q;
110 rhoerror = (r_n + tempalt) * clat - rho;
111 zerror = (r_n * (1.0 - NAV_E2) + tempalt) * slat - xyz[2];
119 double aa = drdl * clat - (r_n + tempalt) * slat;
121 double cc = (1.0 - NAV_E2)*(drdl * slat + r_n * clat);
126 double invdet = 1.0 / (aa * dd - bb * cc);
127 templat = templat - invdet * (+dd * rhoerror - bb * zerror);
128 tempalt = tempalt - invdet * (-cc * rhoerror + aa * zerror);
133 std::cout <<
"xyz2lla could not converge" << std::endl;
138 lla[0] = templat*rad2deg;
147 bool lla2xyz(
double xyz[3],
const double lla[3]){
149 if ((lla[0] < -90.0) | (lla[0] > +90.0) | (lla[1] < -180.0) | (lla[1] > +360.0)){
150 std::cout <<
"WGS lat or WGS lon out of range" << std::endl;
154 double A_EARTH = 6378137.0;
155 double flattening = 1.0/298.257223563;
156 double NAV_E2 = (2.0-flattening)*flattening;
157 double deg2rad = M_PI_R/180.0;
159 double slat = sin(lla[0]*deg2rad);
160 double clat = cos(lla[0]*deg2rad);
161 double r_n = A_EARTH/sqrt(1.0 - NAV_E2*slat*slat);
162 xyz[0] = (r_n + lla[2])*clat*cos(lla[1]*deg2rad);
163 xyz[1] = (r_n + lla[2])*clat*sin(lla[1]*deg2rad);
164 xyz[2] = (r_n*(1.0 - NAV_E2) + lla[2])*slat;
172 bool enu2xyz(
double xyz[3],
const double enu[3],
const double ref_lla[3]){
176 if(!enu2lla(lla,enu, ref_lla))
180 if(!lla2xyz(xyz,lla))
189 bool xyz2enu(
double enu[3],
const double xyz[3],
const double ref_lla[3]){
191 double ref_xyz[3],diff_xyz[3],R[3][3];
194 if (!lla2xyz(ref_xyz,ref_lla))
198 diff_xyz[0] = xyz[0] - ref_xyz[0];
199 diff_xyz[1] = xyz[1] - ref_xyz[1];
200 diff_xyz[2] = xyz[2] - ref_xyz[2];
202 rot3d(R, ref_lla[0], ref_lla[1]);
204 matrixMultiply(enu,R,diff_xyz);
212 void xyz2enu_vel(
double enu_vel[3],
const double xyz_vel[3],
const double ref_lla[3]){
216 rot3d(R, ref_lla[0], ref_lla[1]);
218 matrixMultiply(enu_vel,R,xyz_vel);
225 void enu2xyz_vel(
double xyz_vel[3],
const double enu_vel[3],
const double ref_lla[3]){
227 double R[3][3],Rt[3][3];
229 rot3d(R, ref_lla[0], ref_lla[1]);
231 transposeMatrix(Rt,R);
233 matrixMultiply(xyz_vel,Rt,enu_vel);
240 void xyz2enu_cov(
double enu_Cov[3][3],
const double xyz_Cov[3][3],
const double ref_lla[3]){
242 double R[3][3],Rt[3][3],Tmp[3][3];
244 rot3d(R, ref_lla[0], ref_lla[1]);
246 transposeMatrix(Rt,R);
248 matrixMultiply(Tmp,xyz_Cov,Rt);
250 matrixMultiply(enu_Cov,R,Tmp);
254 void xyz2enu_cov(
double enu_cov[9],
const double xyz_cov[9],
const double ref_lla[3]){
256 double xyz_Cov[3][3],enu_Cov[3][3];
260 xyz_Cov[i][j]=xyz_cov[3*i+j];
262 double R[3][3],Rt[3][3],Tmp[3][3];
264 rot3d(R, ref_lla[0], ref_lla[1]);
266 transposeMatrix(Rt,R);
268 matrixMultiply(Tmp,xyz_Cov,Rt);
270 matrixMultiply(enu_Cov,R,Tmp);
274 enu_cov[3*i+j] = enu_Cov[i][j];
281 void enu2xyz_cov(
double xyz_Cov[3][3],
const double enu_Cov[3][3],
const double ref_lla[3]){
283 double R[3][3],Rt[3][3],Tmp[3][3];
285 rot3d(R, ref_lla[0], ref_lla[1]);
287 transposeMatrix(Rt,R);
289 matrixMultiply(Tmp,enu_Cov,R);
291 matrixMultiply(xyz_Cov,Rt,Tmp);
295 void enu2xyz_cov(
double xyz_cov[9],
const double enu_cov[9],
const double ref_lla[3]){
297 double xyz_Cov[3][3],enu_Cov[3][3];
301 enu_Cov[i][j]=enu_cov[3*i+j];
303 double R[3][3],Rt[3][3],Tmp[3][3];
305 rot3d(R, ref_lla[0], ref_lla[1]);
307 transposeMatrix(Rt,R);
309 matrixMultiply(Tmp,enu_Cov,R);
311 matrixMultiply(xyz_Cov,Rt,Tmp);
315 xyz_cov[3*i+j] = xyz_Cov[i][j];
323 void rot3d(
double R[3][3],
const double reflat,
const double reflon){
325 double R1[3][3],R2[3][3];
327 rot(R1, 90 + reflon, 3);
328 rot(R2, 90 - reflat, 1);
330 matrixMultiply(R, R2, R1);
336 void matrixMultiply(
double C[3][3],
const double A[3][3],
const double B[3][3]){
338 C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0] + A[0][2] * B[2][0];
339 C[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1] + A[0][2] * B[2][1];
340 C[0][2] = A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2] * B[2][2];
341 C[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0] + A[1][2] * B[2][0];
342 C[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1] + A[1][2] * B[2][1];
343 C[1][2] = A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2] * B[2][2];
344 C[2][0] = A[2][0] * B[0][0] + A[2][1] * B[1][0] + A[2][2] * B[2][0];
345 C[2][1] = A[2][0] * B[0][1] + A[2][1] * B[1][1] + A[2][2] * B[2][1];
346 C[2][2] = A[2][0] * B[0][2] + A[2][1] * B[1][2] + A[2][2] * B[2][2];
353 void matrixMultiply(
double c[3],
const double A[3][3],
const double b[3]){
355 c[0] = A[0][0] * b[0] + A[0][1] * b[1] + A[0][2] * b[2];
356 c[1] = A[1][0] * b[0] + A[1][1] * b[1] + A[1][2] * b[2];
357 c[2] = A[2][0] * b[0] + A[2][1] * b[1] + A[2][2] * b[2];
364 void transposeMatrix(
double At[3][3],
const double A[3][3]){
381 void rot(
double R[3][3],
const double angle,
const int axis) {
383 double cang = cos(angle * M_PI_R / 180);
384 double sang = sin(angle * M_PI_R / 180);
396 }
else if (axis == 2) {
406 }
else if (axis == 3) {