Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
pprz_geodetic_int.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2009 Antoine Drouin <poinix@gmail.com>
3  * 2009-2014 Gautier Hattenberger <gautier.hattenberger@enac.fr>
4  * 2010-2014 Felix Ruess <felix.ruess@gmail.com>
5  *
6  * This file is part of paparazzi.
7  *
8  * paparazzi is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * paparazzi is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with paparazzi; see the file COPYING. If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
30 #include "pprz_geodetic_int.h"
31 #include "pprz_algebra_int.h"
32 
33 
34 void ltp_of_ecef_rmat_from_lla_i(struct Int32RMat *ltp_of_ecef, struct LlaCoor_i *lla)
35 {
36 
37 #if USE_DOUBLE_PRECISION_TRIG
38  int32_t sin_lat = rint(BFP_OF_REAL(sin(RAD_OF_EM7DEG((double)lla->lat)), HIGH_RES_TRIG_FRAC));
39  int32_t cos_lat = rint(BFP_OF_REAL(cos(RAD_OF_EM7DEG((double)lla->lat)), HIGH_RES_TRIG_FRAC));
40  int32_t sin_lon = rint(BFP_OF_REAL(sin(RAD_OF_EM7DEG((double)lla->lon)), HIGH_RES_TRIG_FRAC));
41  int32_t cos_lon = rint(BFP_OF_REAL(cos(RAD_OF_EM7DEG((double)lla->lon)), HIGH_RES_TRIG_FRAC));
42 #else
43  int32_t sin_lat = rint(BFP_OF_REAL(sinf(RAD_OF_EM7DEG((float)lla->lat)), HIGH_RES_TRIG_FRAC));
44  int32_t cos_lat = rint(BFP_OF_REAL(cosf(RAD_OF_EM7DEG((float)lla->lat)), HIGH_RES_TRIG_FRAC));
45  int32_t sin_lon = rint(BFP_OF_REAL(sinf(RAD_OF_EM7DEG((float)lla->lon)), HIGH_RES_TRIG_FRAC));
46  int32_t cos_lon = rint(BFP_OF_REAL(cosf(RAD_OF_EM7DEG((float)lla->lon)), HIGH_RES_TRIG_FRAC));
47 #endif
48 
49  ltp_of_ecef->m[0] = -sin_lon;
50  ltp_of_ecef->m[1] = cos_lon;
51  ltp_of_ecef->m[2] = 0; /* this element is always zero http://en.wikipedia.org/wiki/Geodetic_system#From_ECEF_to_ENU */
52  ltp_of_ecef->m[3] = (int32_t)((-(int64_t)sin_lat * (int64_t)cos_lon) >> HIGH_RES_TRIG_FRAC);
53  ltp_of_ecef->m[4] = (int32_t)((-(int64_t)sin_lat * (int64_t)sin_lon) >> HIGH_RES_TRIG_FRAC);
54  ltp_of_ecef->m[5] = cos_lat;
55  ltp_of_ecef->m[6] = (int32_t)(((int64_t)cos_lat * (int64_t)cos_lon) >> HIGH_RES_TRIG_FRAC);
56  ltp_of_ecef->m[7] = (int32_t)(((int64_t)cos_lat * (int64_t)sin_lon) >> HIGH_RES_TRIG_FRAC);
57  ltp_of_ecef->m[8] = sin_lat;
58 }
59 
60 void ltp_def_from_ecef_i(struct LtpDef_i *def, struct EcefCoor_i *ecef)
61 {
62 
63  /* store the origin of the tangeant plane */
64  VECT3_COPY(def->ecef, *ecef);
65  /* compute the lla representation of the origin */
66  lla_of_ecef_i(&def->lla, &def->ecef);
67  /* store the rotation matrix */
69 
70 }
71 
72 void ltp_def_from_lla_i(struct LtpDef_i *def, struct LlaCoor_i *lla)
73 {
74 
75  /* store the origin of the tangeant plane */
76  LLA_COPY(def->lla, *lla);
77  /* compute the ecef representation of the origin */
78  ecef_of_lla_i(&def->ecef, &def->lla);
79  /* store the rotation matrix */
81 
82 }
83 
84 
90 void enu_of_ecef_point_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct EcefCoor_i *ecef)
91 {
92 
93  struct EcefCoor_i delta;
94  VECT3_DIFF(delta, *ecef, def->ecef);
95  const int64_t tmpx = (int64_t)def->ltp_of_ecef.m[0] * delta.x +
96  (int64_t)def->ltp_of_ecef.m[1] * delta.y +
97  0; /* this element is always zero http://en.wikipedia.org/wiki/Geodetic_system#From_ECEF_to_ENU */
98  enu->x = (int32_t)(tmpx >> HIGH_RES_TRIG_FRAC);
99  const int64_t tmpy = (int64_t)def->ltp_of_ecef.m[3] * delta.x +
100  (int64_t)def->ltp_of_ecef.m[4] * delta.y +
101  (int64_t)def->ltp_of_ecef.m[5] * delta.z;
102  enu->y = (int32_t)(tmpy >> HIGH_RES_TRIG_FRAC);
103  const int64_t tmpz = (int64_t)def->ltp_of_ecef.m[6] * delta.x +
104  (int64_t)def->ltp_of_ecef.m[7] * delta.y +
105  (int64_t)def->ltp_of_ecef.m[8] * delta.z;
106  enu->z = (int32_t)(tmpz >> HIGH_RES_TRIG_FRAC);
107 
108 }
109 
110 
116 void ned_of_ecef_point_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct EcefCoor_i *ecef)
117 {
118  struct EnuCoor_i enu;
119  enu_of_ecef_point_i(&enu, def, ecef);
120  ENU_OF_TO_NED(*ned, enu);
121 }
122 
123 
129 void enu_of_ecef_pos_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct EcefCoor_i *ecef)
130 {
131  struct EnuCoor_i enu_cm;
132  enu_of_ecef_point_i(&enu_cm, def, ecef);
133 
134  /* enu = (enu_cm / 100) << INT32_POS_FRAC
135  * to loose less range:
136  * enu_cm = enu << (INT32_POS_FRAC-2) / 25
137  * which puts max enu output Q23.8 range to 8388km / 25 = 335km
138  */
139  INT32_VECT3_LSHIFT(*enu, enu_cm, INT32_POS_FRAC - 2);
140  VECT3_SDIV(*enu, *enu, 25);
141 }
142 
143 
149 void ned_of_ecef_pos_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct EcefCoor_i *ecef)
150 {
151  struct EnuCoor_i enu;
152  enu_of_ecef_pos_i(&enu, def, ecef);
153  ENU_OF_TO_NED(*ned, enu);
154 }
155 
156 
162 void enu_of_ecef_vect_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct EcefCoor_i *ecef)
163 {
164 
165  const int64_t tmpx = (int64_t)def->ltp_of_ecef.m[0] * ecef->x +
166  (int64_t)def->ltp_of_ecef.m[1] * ecef->y +
167  0; /* this element is always zero http://en.wikipedia.org/wiki/Geodetic_system#From_ECEF_to_ENU */
168  enu->x = (int32_t)(tmpx >> HIGH_RES_TRIG_FRAC);
169  const int64_t tmpy = (int64_t)def->ltp_of_ecef.m[3] * ecef->x +
170  (int64_t)def->ltp_of_ecef.m[4] * ecef->y +
171  (int64_t)def->ltp_of_ecef.m[5] * ecef->z;
172  enu->y = (int32_t)(tmpy >> HIGH_RES_TRIG_FRAC);
173  const int64_t tmpz = (int64_t)def->ltp_of_ecef.m[6] * ecef->x +
174  (int64_t)def->ltp_of_ecef.m[7] * ecef->y +
175  (int64_t)def->ltp_of_ecef.m[8] * ecef->z;
176  enu->z = (int32_t)(tmpz >> HIGH_RES_TRIG_FRAC);
177 
178 }
179 
180 
186 void ned_of_ecef_vect_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct EcefCoor_i *ecef)
187 {
188  struct EnuCoor_i enu;
189  enu_of_ecef_vect_i(&enu, def, ecef);
190  ENU_OF_TO_NED(*ned, enu);
191 }
192 
193 
199 void ecef_of_enu_vect_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct EnuCoor_i *enu)
200 {
201 
202  const int64_t tmpx = (int64_t)def->ltp_of_ecef.m[0] * enu->x +
203  (int64_t)def->ltp_of_ecef.m[3] * enu->y +
204  (int64_t)def->ltp_of_ecef.m[6] * enu->z;
205  ecef->x = (int32_t)(tmpx >> HIGH_RES_TRIG_FRAC);
206 
207  const int64_t tmpy = (int64_t)def->ltp_of_ecef.m[1] * enu->x +
208  (int64_t)def->ltp_of_ecef.m[4] * enu->y +
209  (int64_t)def->ltp_of_ecef.m[7] * enu->z;
210  ecef->y = (int32_t)(tmpy >> HIGH_RES_TRIG_FRAC);
211 
212  /* first element is always zero http://en.wikipedia.org/wiki/Geodetic_system#From_ENU_to_ECEF */
213  const int64_t tmpz = (int64_t)def->ltp_of_ecef.m[5] * enu->y +
214  (int64_t)def->ltp_of_ecef.m[8] * enu->z;
215  ecef->z = (int32_t)(tmpz >> HIGH_RES_TRIG_FRAC);
216 
217 }
218 
219 
225 void ecef_of_ned_vect_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct NedCoor_i *ned)
226 {
227  struct EnuCoor_i enu;
228  ENU_OF_TO_NED(enu, *ned);
229  ecef_of_enu_vect_i(ecef, def, &enu);
230 }
231 
232 
238 void ecef_of_enu_point_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct EnuCoor_i *enu)
239 {
240  ecef_of_enu_vect_i(ecef, def, enu);
241  VECT3_ADD(*ecef, def->ecef);
242 }
243 
244 
250 void ecef_of_ned_point_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct NedCoor_i *ned)
251 {
252  struct EnuCoor_i enu;
253  ENU_OF_TO_NED(enu, *ned);
254  ecef_of_enu_point_i(ecef, def, &enu);
255 }
256 
257 
263 void ecef_of_enu_pos_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct EnuCoor_i *enu)
264 {
265  /* enu_cm = (enu * 100) >> INT32_POS_FRAC
266  * to loose less range:
267  * enu_cm = (enu * 25) >> (INT32_POS_FRAC-2)
268  * which puts max enu input Q23.8 range to 8388km / 25 = 335km
269  */
270  struct EnuCoor_i enu_cm;
271  VECT3_SMUL(enu_cm, *enu, 25);
272  INT32_VECT3_RSHIFT(enu_cm, enu_cm, INT32_POS_FRAC - 2);
273  ecef_of_enu_vect_i(ecef, def, &enu_cm);
274  VECT3_ADD(*ecef, def->ecef);
275 }
276 
277 
283 void ecef_of_ned_pos_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct NedCoor_i *ned)
284 {
285  struct EnuCoor_i enu;
286  ENU_OF_TO_NED(enu, *ned);
287  ecef_of_enu_pos_i(ecef, def, &enu);
288 }
289 
295 void enu_of_lla_point_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct LlaCoor_i *lla)
296 {
297  struct EcefCoor_i ecef;
298  ecef_of_lla_i(&ecef, lla);
299  enu_of_ecef_point_i(enu, def, &ecef);
300 }
301 
307 void ned_of_lla_point_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct LlaCoor_i *lla)
308 {
309  struct EcefCoor_i ecef;
310  ecef_of_lla_i(&ecef, lla);
311  ned_of_ecef_point_i(ned, def, &ecef);
312 }
313 
314 void enu_of_lla_vect_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct LlaCoor_i *lla)
315 {
316  struct EcefCoor_i ecef;
317  ecef_of_lla_i(&ecef, lla);
318  enu_of_ecef_vect_i(enu, def, &ecef);
319 }
320 
321 void ned_of_lla_vect_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct LlaCoor_i *lla)
322 {
323  struct EcefCoor_i ecef;
324  ecef_of_lla_i(&ecef, lla);
325  ned_of_ecef_vect_i(ned, def, &ecef);
326 }
327 
328 /*
329  For now we cheat and call the floating point version
330  Anyone up for writing it in fixed point ?
331 */
332 #include "pprz_geodetic_float.h"
333 #include "pprz_geodetic_double.h"
334 
335 void lla_of_ecef_i(struct LlaCoor_i *out, struct EcefCoor_i *in)
336 {
337 
338 #if USE_SINGLE_PRECISION_LLA_ECEF
339  /* convert our input to floating point */
340  struct EcefCoor_f in_f;
341  in_f.x = M_OF_CM((float)in->x);
342  in_f.y = M_OF_CM((float)in->y);
343  in_f.z = M_OF_CM((float)in->z);
344  /* calls the floating point transformation */
345  struct LlaCoor_f out_f;
346  lla_of_ecef_f(&out_f, &in_f);
347  /* convert the output to fixed point */
348  out->lon = (int32_t)rint(EM7DEG_OF_RAD(out_f.lon));
349  out->lat = (int32_t)rint(EM7DEG_OF_RAD(out_f.lat));
350  out->alt = (int32_t)MM_OF_M(out_f.alt);
351 #else // use double precision by default
352  /* convert our input to floating point */
353  struct EcefCoor_d in_d;
354  in_d.x = M_OF_CM((double)in->x);
355  in_d.y = M_OF_CM((double)in->y);
356  in_d.z = M_OF_CM((double)in->z);
357  /* calls the floating point transformation */
358  struct LlaCoor_d out_d;
359  lla_of_ecef_d(&out_d, &in_d);
360  /* convert the output to fixed point */
361  out->lon = (int32_t)rint(EM7DEG_OF_RAD(out_d.lon));
362  out->lat = (int32_t)rint(EM7DEG_OF_RAD(out_d.lat));
363  out->alt = (int32_t)MM_OF_M(out_d.alt);
364 #endif
365 
366 }
367 
368 void ecef_of_lla_i(struct EcefCoor_i *out, struct LlaCoor_i *in)
369 {
370 
371 #if USE_SINGLE_PRECISION_LLA_ECEF
372  /* convert our input to floating point */
373  struct LlaCoor_f in_f;
374  in_f.lon = RAD_OF_EM7DEG((float)in->lon);
375  in_f.lat = RAD_OF_EM7DEG((float)in->lat);
376  in_f.alt = M_OF_MM((float)in->alt);
377  /* calls the floating point transformation */
378  struct EcefCoor_f out_f;
379  ecef_of_lla_f(&out_f, &in_f);
380  /* convert the output to fixed point */
381  out->x = (int32_t)CM_OF_M(out_f.x);
382  out->y = (int32_t)CM_OF_M(out_f.y);
383  out->z = (int32_t)CM_OF_M(out_f.z);
384 #else // use double precision by default
385  /* convert our input to floating point */
386  struct LlaCoor_d in_d;
387  in_d.lon = RAD_OF_EM7DEG((double)in->lon);
388  in_d.lat = RAD_OF_EM7DEG((double)in->lat);
389  in_d.alt = M_OF_MM((double)in->alt);
390  /* calls the floating point transformation */
391  struct EcefCoor_d out_d;
392  ecef_of_lla_d(&out_d, &in_d);
393  /* convert the output to fixed point */
394  out->x = (int32_t)CM_OF_M(out_d.x);
395  out->y = (int32_t)CM_OF_M(out_d.y);
396  out->z = (int32_t)CM_OF_M(out_d.z);
397 #endif
398 
399 }
void ecef_of_enu_pos_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct EnuCoor_i *enu)
Convert a local ENU position to ECEF.
double z
in meters
int32_t z
in centimeters
#define INT32_VECT3_LSHIFT(_o, _i, _l)
#define VECT3_ADD(_a, _b)
Definition: pprz_algebra.h:146
void ecef_of_ned_point_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct NedCoor_i *ned)
Convert a point in local NED to ECEF.
definition of the local (flat earth) coordinate system
int32_t y
North.
int32_t x
East.
#define HIGH_RES_TRIG_FRAC
void ecef_of_enu_point_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct EnuCoor_i *enu)
Convert a point in local ENU to ECEF.
void enu_of_ecef_pos_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct EcefCoor_i *ecef)
Convert a ECEF position to local ENU.
vector in EarthCenteredEarthFixed coordinates
vector in EarthCenteredEarthFixed coordinates
int32_t y
in centimeters
struct Int32RMat ltp_of_ecef
Rotation matrix.
#define M_OF_CM(_cm)
#define VECT3_COPY(_a, _b)
Definition: pprz_algebra.h:139
#define VECT3_DIFF(_c, _a, _b)
Definition: pprz_algebra.h:181
#define CM_OF_M(_m)
double lat
in radians
double alt
in meters above WGS84 reference ellipsoid
int32_t m[3 *3]
float x
in meters
#define INT32_VECT3_RSHIFT(_o, _i, _r)
vector in Latitude, Longitude and Altitude
#define RAD_OF_EM7DEG(_r)
signed long long int64_t
Definition: types.h:21
vector in Latitude, Longitude and Altitude
void ltp_def_from_lla_i(struct LtpDef_i *def, struct LlaCoor_i *lla)
void ned_of_ecef_vect_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct EcefCoor_i *ecef)
Rotate a vector from ECEF to NED.
struct EcefCoor_i ecef
Reference point in ecef.
int32_t alt
in millimeters above WGS84 reference ellipsoid
#define ENU_OF_TO_NED(_po, _pi)
Definition: pprz_geodetic.h:41
Paparazzi double-precision floating point math for geodetic calculations.
Paparazzi floating point math for geodetic calculations.
#define BFP_OF_REAL(_vr, _frac)
vector in Latitude, Longitude and Altitude
double y
in meters
float z
in meters
double x
in meters
void ned_of_ecef_pos_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct EcefCoor_i *ecef)
Convert a ECEF position to local NED.
#define EM7DEG_OF_RAD(_r)
#define VECT3_SDIV(_vo, _vi, _s)
Definition: pprz_algebra.h:195
void enu_of_ecef_point_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct EcefCoor_i *ecef)
Convert a point from ECEF to local ENU.
struct LlaCoor_i lla
Reference point in lla.
int32_t lon
in degrees*1e7
void ecef_of_lla_f(struct EcefCoor_f *out, struct LlaCoor_f *in)
Paparazzi fixed point math for geodetic calculations.
int32_t z
Up.
#define INT32_POS_FRAC
vector in EarthCenteredEarthFixed coordinates
float y
in meters
void lla_of_ecef_d(struct LlaCoor_d *lla, struct EcefCoor_d *ecef)
#define LLA_COPY(_pos1, _pos2)
Definition: pprz_geodetic.h:53
signed long int32_t
Definition: types.h:19
float alt
in meters above WGS84 reference ellipsoid
void ecef_of_ned_pos_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct NedCoor_i *ned)
Convert a local NED position to ECEF.
#define VECT3_SMUL(_vo, _vi, _s)
Definition: pprz_algebra.h:188
void ned_of_lla_point_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct LlaCoor_i *lla)
Convert a point from LLA to local NED.
#define MM_OF_M(_m)
vector in East North Up coordinates
vector in North East Down coordinates
void ned_of_ecef_point_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct EcefCoor_i *ecef)
Convert a point from ECEF to local NED.
double lon
in radians
void enu_of_ecef_vect_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct EcefCoor_i *ecef)
Rotate a vector from ECEF to ENU.
float lon
in radians
int32_t x
in centimeters
rotation matrix
void ecef_of_lla_i(struct EcefCoor_i *out, struct LlaCoor_i *in)
#define M_OF_MM(_mm)
float lat
in radians
void ltp_of_ecef_rmat_from_lla_i(struct Int32RMat *ltp_of_ecef, struct LlaCoor_i *lla)
void lla_of_ecef_i(struct LlaCoor_i *out, struct EcefCoor_i *in)
void enu_of_lla_point_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct LlaCoor_i *lla)
Convert a point from LLA to local ENU.
int32_t lat
in degrees*1e7
void ecef_of_lla_d(struct EcefCoor_d *ecef, struct LlaCoor_d *lla)
void lla_of_ecef_f(struct LlaCoor_f *out, struct EcefCoor_f *in)
void ned_of_lla_vect_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct LlaCoor_i *lla)
void enu_of_lla_vect_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct LlaCoor_i *lla)
void ecef_of_enu_vect_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct EnuCoor_i *enu)
Rotate a vector from ENU to ECEF.
void ltp_def_from_ecef_i(struct LtpDef_i *def, struct EcefCoor_i *ecef)
Paparazzi fixed point algebra.
void ecef_of_ned_vect_i(struct EcefCoor_i *ecef, struct LtpDef_i *def, struct NedCoor_i *ned)
Rotate a vector from NED to ECEF.