Skip to content

Commit 811ada3

Browse files
committed
[Feature] Added function for converting gps coordinates to relative local
1 parent f2f5f6a commit 811ada3

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

math/gps_util.h

+42
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#ifndef GPS_UTIL_H_
22
#define GPS_UTIL_H_
33

4+
#include "eigen3/Eigen/Dense"
45
#include <math.h>
56
#include <tuple>
67

78
namespace gps_util {
9+
810
inline std::tuple<double, double, int> gpsToUTM(double lat, double lon) {
911
// Constants for UTM conversion
1012
constexpr double a = 6378137.0; // WGS-84 major axis
@@ -56,6 +58,46 @@ inline std::tuple<double, double> gpsToGlobalCoord(double lat0, double lon0, dou
5658
const auto& [e1, n1, zone1] = gpsToUTM(lat1, lon1);
5759
return {e1 - e0, n1 - n0};
5860
}
61+
62+
inline Eigen::Affine2f gpsToLocal(
63+
double current_lat, double current_lon, double current_heading,
64+
double goal_lat, double goal_lon, double goal_heading) {
65+
66+
// Step 1: Convert current and goal GPS coordinates to UTM
67+
const auto& [curr_easting, curr_northing, curr_zone] = gpsToUTM(current_lat, current_lon);
68+
const auto& [goal_easting, goal_northing, goal_zone] = gpsToUTM(goal_lat, goal_lon);
69+
// Ensure that both coordinates are in the same UTM zone
70+
if (goal_zone != curr_zone) {
71+
throw std::runtime_error("GPS points are in different UTM zones.");
72+
}
73+
74+
// Step 2: Calculate the translation vector from the current position to the goal in UTM
75+
double dx = goal_easting - curr_easting;
76+
double dy = goal_northing - curr_northing;
77+
78+
// Step 3: Convert the current heading to radians and adjust for x-axis reference
79+
// Since 0 degrees points along the y-axis and rotates counter-clockwise,
80+
// convert to radians with 0 degrees aligned along the x-axis
81+
double current_heading_rad = (90.0 - current_heading) * M_PI / 180.0;
82+
83+
// Step 4: Rotate the translation vector to the robot's local frame
84+
double local_x = dx * cos(-current_heading_rad) - dy * sin(-current_heading_rad);
85+
double local_y = dx * sin(-current_heading_rad) + dy * cos(-current_heading_rad);
86+
87+
// Step 5: Convert the goal heading to the local frame
88+
double goal_heading_rad = (90.0 - goal_heading) * M_PI / 180.0;
89+
double local_heading = goal_heading_rad - current_heading_rad;
90+
91+
// Normalize local heading to the range [-pi, pi]
92+
while (local_heading > M_PI) local_heading -= 2 * M_PI;
93+
while (local_heading < -M_PI) local_heading += 2 * M_PI;
94+
95+
// Step 6: Create the affine transformation for the local pose of the goal
96+
Eigen::Affine2f transform = Eigen::Translation2f(local_x, local_y) * Eigen::Rotation2Df(local_heading);
97+
98+
return transform;
99+
}
100+
59101
}
60102

61103
#endif

0 commit comments

Comments
 (0)