dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
coordinateconversions.cpp
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  */
28 #define _USE_MATH_DEFINES
29 #include <cmath>
30 #include "coordinateconversions.h"
31 #include <qglobal.h>
32 #include <QDebug>
33 #include <math.h>
34 
35 #include <physical_constants.h>
36 
37 namespace Utils {
38 
39 const double CoordinateConversions::R_EQUATOR = 6378137.0;
40 const double CoordinateConversions::ECCENTRICITY = 8.1819190842621e-2;
41 
43 {
44 
45 }
46 
52 void CoordinateConversions::LLA2Rne(double LLA[3], double Rne[3][3]){
53  float sinLat, sinLon, cosLat, cosLon;
54 
55  sinLat=(float)sin(DEG2RAD*LLA[0]);
56  sinLon=(float)sin(DEG2RAD*LLA[1]);
57  cosLat=(float)cos(DEG2RAD*LLA[0]);
58  cosLon=(float)cos(DEG2RAD*LLA[1]);
59 
60  Rne[0][0] = -sinLat*cosLon; Rne[0][1] = -sinLat*sinLon; Rne[0][2] = cosLat;
61  Rne[1][0] = -sinLon; Rne[1][1] = cosLon; Rne[1][2] = 0;
62  Rne[2][0] = -cosLat*cosLon; Rne[2][1] = -cosLat*sinLon; Rne[2][2] = -sinLat;
63 }
64 
70 void CoordinateConversions::LLA2ECEF(double LLA[3], double ECEF[3]){
71  const double a = R_EQUATOR; // Equatorial Radius
72  const double e = ECCENTRICITY; // Eccentricity
73  double sinLat, sinLon, cosLat, cosLon;
74  double N;
75 
76  sinLat=sin(DEG2RAD*LLA[0]);
77  sinLon=sin(DEG2RAD*LLA[1]);
78  cosLat=cos(DEG2RAD*LLA[0]);
79  cosLon=cos(DEG2RAD*LLA[1]);
80 
81  N = a / sqrt(1.0 - e*e*sinLat*sinLat); //prime vertical radius of curvature
82 
83  ECEF[0] = (N+LLA[2])*cosLat*cosLon;
84  ECEF[1] = (N+LLA[2])*cosLat*sinLon;
85  ECEF[2] = ((1-e*e)*N + LLA[2]) * sinLat;
86 }
87 
93 int CoordinateConversions::ECEF2LLA(double ECEF[3], double LLA[3])
94 {
95  const double a = R_EQUATOR; // Equatorial Radius
96  const double e = ECCENTRICITY; // Eccentricity
97  double x=ECEF[0], y=ECEF[1], z=ECEF[2];
98  double Lat, N, NplusH, delta, esLat;
99  quint16 iter;
100 
101  LLA[1] = RAD2DEG*atan2(y,x);
102  N = a;
103  NplusH = N;
104  delta = 1;
105  Lat = 1;
106  iter=0;
107 
108  while (((delta > 1.0e-14)||(delta < -1.0e-14)) && (iter < 100))
109  {
110  delta = Lat - atan(z / (sqrt(x*x + y*y)*(1-(N*e*e/NplusH))));
111  Lat = Lat-delta;
112  esLat = e*sin(Lat);
113  N = a / sqrt(1 - esLat*esLat);
114  NplusH = sqrt(x*x + y*y)/cos(Lat);
115  iter += 1;
116  }
117 
118  LLA[0] = RAD2DEG*Lat;
119  LLA[2] = NplusH - N;
120 
121  if (iter==500) return (0);
122  else return (1);
123 }
124 
134 int CoordinateConversions::NED2LLA_HomeECEF(double BaseECEF[3], double NED[3], double LLA[3])
135 {
136  int i;
137  double BaseLLA[3];
138  double ECEF[3];
139  double Rne [3][3];
140 
141  // Get LLA address to compute conversion matrix
142  ECEF2LLA(BaseECEF, BaseLLA);
143  LLA2Rne(BaseLLA, Rne);
144 
145  /* P = ECEF + Rne' * NED */
146  for(i = 0; i < 3; i++)
147  ECEF[i] = BaseECEF[i] + Rne[0][i]*NED[0] + Rne[1][i]*NED[1] + Rne[2][i]*NED[2];
148 
149  ECEF2LLA(ECEF,LLA);
150 
151  return 0;
152 }
153 
163 int CoordinateConversions::NED2LLA_HomeLLA(double homeLLA[3], double NED[3], double LLA[3])
164 {
165  double T[3];
166  // 6.378137E6 is the radius of the earth
167  T[0] = homeLLA[2]+6.378137E6f * M_PI / 180.0;
168  T[1] = cosf(homeLLA[0] * M_PI / 180.0)*(homeLLA[2]+6.378137E6f) * M_PI / 180.0;
169  T[2] = -1.0f;
170 
171  LLA[0] = homeLLA[0] + NED[0] / T[0];
172  LLA[1] = homeLLA[1] + NED[1] / T[1];
173  LLA[2] = homeLLA[2] + NED[2] / T[2];
174 
175  return 0;
176 }
177 
188 void CoordinateConversions::LLA2NED_HomeECEF(double LLA[3], double BaseECEF[3], double Rne[3][3], double NED[3])
189 {
190  double ECEF[3];
191  double diff[3];
192 
193  LLA2ECEF(LLA, ECEF);
194 
195  diff[0] = ECEF[0] - BaseECEF[0];
196  diff[1] = ECEF[1] - BaseECEF[1];
197  diff[2] = ECEF[2] - BaseECEF[2];
198 
199  NED[0] = Rne[0][0] * diff[0] + Rne[0][1] * diff[1] + Rne[0][2] * diff[2];
200  NED[1] = Rne[1][0] * diff[0] + Rne[1][1] * diff[1] + Rne[1][2] * diff[2];
201  NED[2] = Rne[2][0] * diff[0] + Rne[2][1] * diff[1] + Rne[2][2] * diff[2];
202 }
203 
213 void CoordinateConversions::LLA2NED_HomeLLA(double LLA[3], double homeLLA[3], double NED[3])
214 {
215  double lat = homeLLA[0] * DEG2RAD;
216  double alt = homeLLA[2];
217 
218  float T[3];
219  T[0] = alt+6.378137E6;
220  T[1] = cos(lat)*(alt+6.378137E6);
221  T[2] = -1.0;
222 
223  float dL[3];
224  dL[0] = (float)((LLA[0] - homeLLA[0]) * DEG2RAD);
225  dL[1] = (float)((LLA[1] - homeLLA[1]) * DEG2RAD);
226  dL[2] = (float)(LLA[2] - homeLLA[2]);
227 
228  NED[0] = T[0] * dL[0];
229  NED[1] = T[1] * dL[1];
230  NED[2] = T[2] * dL[2];
231 }
232 
233 // ****** find roll, pitch, yaw from quaternion ********
234 void CoordinateConversions::Quaternion2RPY(const float q[4], float rpy[3])
235 {
236  float R13, R11, R12, R23, R33;
237  float q0s = q[0] * q[0];
238  float q1s = q[1] * q[1];
239  float q2s = q[2] * q[2];
240  float q3s = q[3] * q[3];
241 
242  R13 = 2 * (q[1] * q[3] - q[0] * q[2]);
243  R11 = q0s + q1s - q2s - q3s;
244  R12 = 2 * (q[1] * q[2] + q[0] * q[3]);
245  R23 = 2 * (q[2] * q[3] + q[0] * q[1]);
246  R33 = q0s - q1s - q2s + q3s;
247 
248  rpy[1] = RAD2DEG * asinf(-R13); // pitch always between -pi/2 to pi/2
249  rpy[2] = RAD2DEG * atan2f(R12, R11);
250  rpy[0] = RAD2DEG * atan2f(R23, R33);
251 
252  //TODO: consider the cases where |R13| ~= 1, |pitch| ~= pi/2
253 }
254 
255 // ****** find quaternion from roll, pitch, yaw ********
256 void CoordinateConversions::RPY2Quaternion(const float rpy[3], float q[4])
257 {
258  float phi, theta, psi;
259  float cphi, sphi, ctheta, stheta, cpsi, spsi;
260 
261  phi = DEG2RAD * rpy[0] / 2;
262  theta = DEG2RAD * rpy[1] / 2;
263  psi = DEG2RAD * rpy[2] / 2;
264  cphi = cosf(phi);
265  sphi = sinf(phi);
266  ctheta = cosf(theta);
267  stheta = sinf(theta);
268  cpsi = cosf(psi);
269  spsi = sinf(psi);
270 
271  q[0] = cphi * ctheta * cpsi + sphi * stheta * spsi;
272  q[1] = sphi * ctheta * cpsi - cphi * stheta * spsi;
273  q[2] = cphi * stheta * cpsi + sphi * ctheta * spsi;
274  q[3] = cphi * ctheta * spsi - sphi * stheta * cpsi;
275 
276  if (q[0] < 0) { // q0 always positive for uniqueness
277  q[0] = -q[0];
278  q[1] = -q[1];
279  q[2] = -q[2];
280  q[3] = -q[3];
281  }
282 }
283 
284 //** Find Rbe, that rotates a vector from earth fixed to body frame, from quaternion **
285 void CoordinateConversions::Quaternion2R(const float q[4], float Rbe[3][3])
286 {
287 
288  float q0s = q[0] * q[0], q1s = q[1] * q[1], q2s = q[2] * q[2], q3s = q[3] * q[3];
289 
290  Rbe[0][0] = q0s + q1s - q2s - q3s;
291  Rbe[0][1] = 2 * (q[1] * q[2] + q[0] * q[3]);
292  Rbe[0][2] = 2 * (q[1] * q[3] - q[0] * q[2]);
293  Rbe[1][0] = 2 * (q[1] * q[2] - q[0] * q[3]);
294  Rbe[1][1] = q0s - q1s + q2s - q3s;
295  Rbe[1][2] = 2 * (q[2] * q[3] + q[0] * q[1]);
296  Rbe[2][0] = 2 * (q[1] * q[3] + q[0] * q[2]);
297  Rbe[2][1] = 2 * (q[2] * q[3] - q[0] * q[1]);
298  Rbe[2][2] = q0s - q1s - q2s + q3s;
299 }
300 
301 //** Find quaternion vector from a rotation matrix, Rbe, a matrix which rotates a vector from earth frame to body frame **
302 void CoordinateConversions::R2Quaternion(float const Rbe[3][3], float q[4])
303 {
304  qreal w, x, y, z;
305 
306  // w always >= 0
307  w = sqrt(std::max(0.0, 1.0 + Rbe[0][0] + Rbe[1][1] + Rbe[2][2])) / 2.0;
308  x = sqrt(std::max(0.0, 1.0 + Rbe[0][0] - Rbe[1][1] - Rbe[2][2])) / 2.0;
309  y = sqrt(std::max(0.0, 1.0 - Rbe[0][0] + Rbe[1][1] - Rbe[2][2])) / 2.0;
310  z = sqrt(std::max(0.0, 1.0 - Rbe[0][0] - Rbe[1][1] + Rbe[2][2])) / 2.0;
311 
312  x = copysign(x, (Rbe[1][2] - Rbe[2][1]));
313  y = copysign(y, (Rbe[2][0] - Rbe[0][2]));
314  z = copysign(z, (Rbe[0][1] - Rbe[1][0]));
315 
316  q[0]=w;
317  q[1]=x;
318  q[2]=y;
319  q[3]=z;
320 }
321 
322 
323 }
void LLA2ECEF(double LLA[3], double ECEF[3])
iter
Definition: OPPlots.m:115
void RPY2Quaternion(const float rpy[3], float q[4])
BaseECEF
Definition: OPPlots.m:37
cosLat
Definition: OPPlots.m:143
DEG2RAD
Definition: OPPlots.m:107
diff
Definition: OPPlots.m:68
Rne
Definition: OPPlots.m:38
cosLon
Definition: OPPlots.m:144
sinLon
Definition: OPPlots.m:142
axis equal end function NED
Definition: OPPlots.m:63
void LLA2NED_HomeLLA(double LLA[3], double homeLLA[3], double NED[3])
for i
Definition: OPPlots.m:140
int ECEF2LLA(double ECEF[3], double LLA[3])
void LLA2NED_HomeECEF(double LLA[3], double homeECEF[3], double Rne[3][3], double NED[3])
end a
Definition: OPPlots.m:98
Lat
Definition: OPPlots.m:110
NplusH
Definition: OPPlots.m:113
z
Definition: OPPlots.m:102
int NED2LLA_HomeLLA(double homeLLA[3], double NED[3], double LLA[3])
void Quaternion2R(const float q[4], float Rbe[3][3])
void Quaternion2RPY(const float q[4], float rpy[3])
sinLat
Definition: OPPlots.m:159
RAD2DEG
Definition: OPPlots.m:106
delta
Definition: OPPlots.m:114
LLA
Definition: OPPlots.m:34
x
Definition: OPPlots.m:100
ECEF
Definition: OPPlots.m:66
void LLA2Rne(double LLA[3], double Rne[3][3])
N
Definition: OPPlots.m:112
esLat
Definition: OPPlots.m:111
void R2Quaternion(float const Rbe[3][3], float q[4])
e
Definition: OPPlots.m:99
y
Definition: OPPlots.m:101
int NED2LLA_HomeECEF(double BaseECEF[3], double NED[3], double LLA[3])