-
Notifications
You must be signed in to change notification settings - Fork 901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UTM conversions using geographiclib #626
UTM conversions using geographiclib #626
Conversation
e8c54ca
to
ab6e851
Compare
Thanks for this, and for the tests. Are you happy to have this reviewed now? |
Certainly. |
|
||
/** | ||
* Convert lat/long to UTM coords. Equations from USGS Bulletin 1532 | ||
* Convert lat/long to UTM coords. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also get rid of all of this? Or do we still need it?
robot_localization/include/robot_localization/navsat_conversions.h
Lines 65 to 139 in ab6e851
const double RADIANS_PER_DEGREE = M_PI/180.0; | |
const double DEGREES_PER_RADIAN = 180.0/M_PI; | |
// Grid granularity for rounding UTM coordinates to generate MapXY. | |
const double grid_size = 100000.0; // 100 km grid | |
// WGS84 Parameters | |
#define WGS84_A 6378137.0 // major axis | |
#define WGS84_B 6356752.31424518 // minor axis | |
#define WGS84_F 0.0033528107 // ellipsoid flattening | |
#define WGS84_E 0.0818191908 // first eccentricity | |
#define WGS84_EP 0.0820944379 // second eccentricity | |
// UTM Parameters | |
#define UTM_K0 0.9996 // scale factor | |
#define UTM_FE 500000.0 // false easting | |
#define UTM_FN_N 0.0 // false northing, northern hemisphere | |
#define UTM_FN_S 10000000.0 // false northing, southern hemisphere | |
#define UTM_E2 (WGS84_E*WGS84_E) // e^2 | |
#define UTM_E4 (UTM_E2*UTM_E2) // e^4 | |
#define UTM_E6 (UTM_E4*UTM_E2) // e^6 | |
#define UTM_EP2 (UTM_E2/(1-UTM_E2)) // e'^2 | |
/** | |
* Utility function to convert geodetic to UTM position | |
* | |
* Units in are floating point degrees (sign for east/west) | |
* | |
* Units out are meters | |
* | |
* @todo deprecate this interface in favor of LLtoUTM() | |
*/ | |
static inline void UTM(double lat, double lon, double *x, double *y) | |
{ | |
// constants | |
static const double m0 = (1 - UTM_E2/4 - 3*UTM_E4/64 - 5*UTM_E6/256); | |
static const double m1 = -(3*UTM_E2/8 + 3*UTM_E4/32 + 45*UTM_E6/1024); | |
static const double m2 = (15*UTM_E4/256 + 45*UTM_E6/1024); | |
static const double m3 = -(35*UTM_E6/3072); | |
// compute the central meridian | |
int cm = ((lon >= 0.0) | |
? (static_cast<int>(lon) - (static_cast<int>(lon)) % 6 + 3) | |
: (static_cast<int>(lon) - (static_cast<int>(lon)) % 6 - 3)); | |
// convert degrees into radians | |
double rlat = lat * RADIANS_PER_DEGREE; | |
double rlon = lon * RADIANS_PER_DEGREE; | |
double rlon0 = cm * RADIANS_PER_DEGREE; | |
// compute trigonometric functions | |
double slat = sin(rlat); | |
double clat = cos(rlat); | |
double tlat = tan(rlat); | |
// decide the false northing at origin | |
double fn = (lat > 0) ? UTM_FN_N : UTM_FN_S; | |
double T = tlat * tlat; | |
double C = UTM_EP2 * clat * clat; | |
double A = (rlon - rlon0) * clat; | |
double M = WGS84_A * (m0*rlat + m1*sin(2*rlat) | |
+ m2*sin(4*rlat) + m3*sin(6*rlat)); | |
double V = WGS84_A / sqrt(1 - UTM_E2*slat*slat); | |
// compute the easting-northing coordinates | |
*x = UTM_FE + UTM_K0 * V * (A + (1-T+C)*pow(A, 3)/6 | |
+ (5-18*T+T*T+72*C-58*UTM_EP2)*pow(A, 5)/120); | |
*y = fn + UTM_K0 * (M + V * tlat * (A*A/2 | |
+ (5-T+9*C+4*C*C)*pow(A, 4)/24 | |
+ ((61-58*T+T*T+600*C-330*UTM_EP2) | |
* pow(A, 6)/720))); | |
return; | |
} |
And if we do get rid of that, can we also get rid of the other comments and update the license?
robot_localization/include/robot_localization/navsat_conversions.h
Lines 65 to 139 in ab6e851
const double RADIANS_PER_DEGREE = M_PI/180.0; | |
const double DEGREES_PER_RADIAN = 180.0/M_PI; | |
// Grid granularity for rounding UTM coordinates to generate MapXY. | |
const double grid_size = 100000.0; // 100 km grid | |
// WGS84 Parameters | |
#define WGS84_A 6378137.0 // major axis | |
#define WGS84_B 6356752.31424518 // minor axis | |
#define WGS84_F 0.0033528107 // ellipsoid flattening | |
#define WGS84_E 0.0818191908 // first eccentricity | |
#define WGS84_EP 0.0820944379 // second eccentricity | |
// UTM Parameters | |
#define UTM_K0 0.9996 // scale factor | |
#define UTM_FE 500000.0 // false easting | |
#define UTM_FN_N 0.0 // false northing, northern hemisphere | |
#define UTM_FN_S 10000000.0 // false northing, southern hemisphere | |
#define UTM_E2 (WGS84_E*WGS84_E) // e^2 | |
#define UTM_E4 (UTM_E2*UTM_E2) // e^4 | |
#define UTM_E6 (UTM_E4*UTM_E2) // e^6 | |
#define UTM_EP2 (UTM_E2/(1-UTM_E2)) // e'^2 | |
/** | |
* Utility function to convert geodetic to UTM position | |
* | |
* Units in are floating point degrees (sign for east/west) | |
* | |
* Units out are meters | |
* | |
* @todo deprecate this interface in favor of LLtoUTM() | |
*/ | |
static inline void UTM(double lat, double lon, double *x, double *y) | |
{ | |
// constants | |
static const double m0 = (1 - UTM_E2/4 - 3*UTM_E4/64 - 5*UTM_E6/256); | |
static const double m1 = -(3*UTM_E2/8 + 3*UTM_E4/32 + 45*UTM_E6/1024); | |
static const double m2 = (15*UTM_E4/256 + 45*UTM_E6/1024); | |
static const double m3 = -(35*UTM_E6/3072); | |
// compute the central meridian | |
int cm = ((lon >= 0.0) | |
? (static_cast<int>(lon) - (static_cast<int>(lon)) % 6 + 3) | |
: (static_cast<int>(lon) - (static_cast<int>(lon)) % 6 - 3)); | |
// convert degrees into radians | |
double rlat = lat * RADIANS_PER_DEGREE; | |
double rlon = lon * RADIANS_PER_DEGREE; | |
double rlon0 = cm * RADIANS_PER_DEGREE; | |
// compute trigonometric functions | |
double slat = sin(rlat); | |
double clat = cos(rlat); | |
double tlat = tan(rlat); | |
// decide the false northing at origin | |
double fn = (lat > 0) ? UTM_FN_N : UTM_FN_S; | |
double T = tlat * tlat; | |
double C = UTM_EP2 * clat * clat; | |
double A = (rlon - rlon0) * clat; | |
double M = WGS84_A * (m0*rlat + m1*sin(2*rlat) | |
+ m2*sin(4*rlat) + m3*sin(6*rlat)); | |
double V = WGS84_A / sqrt(1 - UTM_E2*slat*slat); | |
// compute the easting-northing coordinates | |
*x = UTM_FE + UTM_K0 * V * (A + (1-T+C)*pow(A, 3)/6 | |
+ (5-18*T+T*T+72*C-58*UTM_EP2)*pow(A, 5)/120); | |
*y = fn + UTM_K0 * (M + V * tlat * (A*A/2 | |
+ (5-T+9*C+4*C*C)*pow(A, 4)/24 | |
+ ((61-58*T+T*T+600*C-330*UTM_EP2) | |
* pow(A, 6)/720))); | |
return; | |
} |
robot_localization/include/robot_localization/navsat_conversions.h
Lines 65 to 139 in ab6e851
const double RADIANS_PER_DEGREE = M_PI/180.0; | |
const double DEGREES_PER_RADIAN = 180.0/M_PI; | |
// Grid granularity for rounding UTM coordinates to generate MapXY. | |
const double grid_size = 100000.0; // 100 km grid | |
// WGS84 Parameters | |
#define WGS84_A 6378137.0 // major axis | |
#define WGS84_B 6356752.31424518 // minor axis | |
#define WGS84_F 0.0033528107 // ellipsoid flattening | |
#define WGS84_E 0.0818191908 // first eccentricity | |
#define WGS84_EP 0.0820944379 // second eccentricity | |
// UTM Parameters | |
#define UTM_K0 0.9996 // scale factor | |
#define UTM_FE 500000.0 // false easting | |
#define UTM_FN_N 0.0 // false northing, northern hemisphere | |
#define UTM_FN_S 10000000.0 // false northing, southern hemisphere | |
#define UTM_E2 (WGS84_E*WGS84_E) // e^2 | |
#define UTM_E4 (UTM_E2*UTM_E2) // e^4 | |
#define UTM_E6 (UTM_E4*UTM_E2) // e^6 | |
#define UTM_EP2 (UTM_E2/(1-UTM_E2)) // e'^2 | |
/** | |
* Utility function to convert geodetic to UTM position | |
* | |
* Units in are floating point degrees (sign for east/west) | |
* | |
* Units out are meters | |
* | |
* @todo deprecate this interface in favor of LLtoUTM() | |
*/ | |
static inline void UTM(double lat, double lon, double *x, double *y) | |
{ | |
// constants | |
static const double m0 = (1 - UTM_E2/4 - 3*UTM_E4/64 - 5*UTM_E6/256); | |
static const double m1 = -(3*UTM_E2/8 + 3*UTM_E4/32 + 45*UTM_E6/1024); | |
static const double m2 = (15*UTM_E4/256 + 45*UTM_E6/1024); | |
static const double m3 = -(35*UTM_E6/3072); | |
// compute the central meridian | |
int cm = ((lon >= 0.0) | |
? (static_cast<int>(lon) - (static_cast<int>(lon)) % 6 + 3) | |
: (static_cast<int>(lon) - (static_cast<int>(lon)) % 6 - 3)); | |
// convert degrees into radians | |
double rlat = lat * RADIANS_PER_DEGREE; | |
double rlon = lon * RADIANS_PER_DEGREE; | |
double rlon0 = cm * RADIANS_PER_DEGREE; | |
// compute trigonometric functions | |
double slat = sin(rlat); | |
double clat = cos(rlat); | |
double tlat = tan(rlat); | |
// decide the false northing at origin | |
double fn = (lat > 0) ? UTM_FN_N : UTM_FN_S; | |
double T = tlat * tlat; | |
double C = UTM_EP2 * clat * clat; | |
double A = (rlon - rlon0) * clat; | |
double M = WGS84_A * (m0*rlat + m1*sin(2*rlat) | |
+ m2*sin(4*rlat) + m3*sin(6*rlat)); | |
double V = WGS84_A / sqrt(1 - UTM_E2*slat*slat); | |
// compute the easting-northing coordinates | |
*x = UTM_FE + UTM_K0 * V * (A + (1-T+C)*pow(A, 3)/6 | |
+ (5-18*T+T*T+72*C-58*UTM_EP2)*pow(A, 5)/120); | |
*y = fn + UTM_K0 * (M + V * tlat * (A*A/2 | |
+ (5-T+9*C+4*C*C)*pow(A, 4)/24 | |
+ ((61-58*T+T*T+600*C-330*UTM_EP2) | |
* pow(A, 6)/720))); | |
return; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can.
I left them in because they are exposed to other packages. So I'm not sure who might be using these variables...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. I'll bring this forward to the ROS2 branches, and for Galactic, I'll remove them. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the whole conversions file can be removed in that case. Since there is now a library doing all that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SteveMacenski, anything glaring to you on this or #627? |
I haven't used geographic lib / GPS before in a product so I can't say I have an opinion. Though I'd want a PR analog to this for ROS2 to keep them in sync |
I could do that. Which branch(es) would I need to target? And which of those would allow breaking changes? |
The ros2 branch would allow breaking changes |
I could not target the ROS2 branch because it's too much behind on Foxy. |
@Timple what do you mean, I'm looking at the ROS2->Foxy diff right here its only off by 4 commits that are just rclcpp API changes (only covering like ~80 lines). We need any changes to Foxy to be in |
Well that is strange. Than how come there is no mention of Did a merge go wrong somewhere? |
I can't think of anything offhand. For the record, the model that I originally tried to follow was;
Obviously, there have been some violations of that paradigm, but that's generally the way I wanted to do things. The
|
Both suggestions result in the
Certainly this. So I'll target the |
The new ROS2-y workflow is
Depending on my laziness, I also sometimes ask people to target their PR to multiple branches (ros2, and foxy, and noetic or something) to avoid the cherry picking later / forgetting. |
* Use GeographicLib for UTMtoLL conversions
For #222 it made sense to use the GeographicLib library that #575 already introduced.
In preparation I rewrote the current UTM functions.