1
1
#ifndef GPS_UTIL_H_
2
2
#define GPS_UTIL_H_
3
3
4
+ #include " eigen3/Eigen/Dense"
4
5
#include < math.h>
5
6
#include < tuple>
6
7
7
8
namespace gps_util {
9
+
8
10
inline std::tuple<double , double , int > gpsToUTM (double lat, double lon) {
9
11
// Constants for UTM conversion
10
12
constexpr double a = 6378137.0 ; // WGS-84 major axis
@@ -56,6 +58,46 @@ inline std::tuple<double, double> gpsToGlobalCoord(double lat0, double lon0, dou
56
58
const auto & [e1 , n1, zone1] = gpsToUTM (lat1, lon1);
57
59
return {e1 - e0 , n1 - n0};
58
60
}
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
+
59
101
}
60
102
61
103
#endif
0 commit comments