@@ -36,10 +36,12 @@ struct GPSPoint {
36
36
double time;
37
37
double lat;
38
38
double lon;
39
- double heading; // True North
39
+ double heading; // True North (degrees)
40
40
};
41
41
42
42
struct GPSTranslator {
43
+ GPSTranslator () : is_origin_set(false ) {}
44
+
43
45
string GetMapFileFromName (const string& maps_dir, const string& map) {
44
46
return maps_dir + " /" + map + " /" + map + " .gpsmap.txt" ;
45
47
}
@@ -54,16 +56,19 @@ struct GPSTranslator {
54
56
}
55
57
printf (" Map origin: %12.8lf, %12.8lf\n " , gps_origin_latitude,
56
58
gps_origin_longitude);
59
+ is_origin_set = true ;
57
60
return true ;
58
61
}
59
62
60
63
void SetOrigin (double latitude, double longitude, double orientation) {
61
64
gps_origin_latitude = latitude;
62
65
gps_origin_longitude = longitude;
63
66
map_orientation = orientation;
67
+ is_origin_set = true ;
64
68
}
65
69
66
70
Vector2d GPSToMetric (const double latitude, const double longitude) {
71
+ CHECK (is_origin_set);
67
72
const double theta = DegToRad (latitude);
68
73
const double c = std::cos (theta);
69
74
const double s = std::sin (theta);
@@ -78,6 +83,7 @@ struct GPSTranslator {
78
83
}
79
84
80
85
void MetricToGPS (const Vector2d& loc, double * longitude, double * latitude) {
86
+ CHECK (is_origin_set);
81
87
const double theta = DegToRad (gps_origin_latitude);
82
88
const double c = std::cos (theta);
83
89
const double s = std::sin (theta);
@@ -93,6 +99,7 @@ struct GPSTranslator {
93
99
double gps_origin_longitude;
94
100
double gps_origin_latitude;
95
101
double map_orientation;
102
+ bool is_origin_set;
96
103
97
104
// Earth geoid parameters from WGS 84 system
98
105
// https://en.wikipedia.org/wiki/World_Geodetic_System#A_new_World_Geodetic_System:_WGS_84
@@ -155,7 +162,9 @@ inline std::tuple<double, double, int> gpsToUTM(double lat, double lon) {
155
162
return std::make_tuple (easting, northing, zone);
156
163
}
157
164
158
- inline double gpsDistance (double lat0, double lon0, double lat1, double lon1) {
165
+ inline double gpsDistance (const GPSPoint& p0, const GPSPoint& p1) {
166
+ const auto & [lat0, lon0] = std::make_tuple (p0.lat , p0.lon );
167
+ const auto & [lat1, lon1] = std::make_tuple (p1.lat , p1.lon );
159
168
// Convert latitude and longitude to radians
160
169
double lat0_rad = lat0 * M_PI / 180.0 ;
161
170
double lon0_rad = lon0 * M_PI / 180.0 ;
@@ -171,53 +180,48 @@ inline double gpsDistance(double lat0, double lon0, double lat1, double lon1) {
171
180
return 6371000 * c; // Radius of Earth in meters
172
181
}
173
182
174
- inline std::tuple<double , double > gpsToGlobalCoord (double lat0, double lon0,
175
- double lat1, double lon1) {
183
+ inline Eigen::Vector2d gpsToGlobalCoord (const GPSPoint& p0,
184
+ const GPSPoint& p1) {
185
+ const auto & [lat0, lon0] = std::make_tuple (p0.lat , p0.lon );
186
+ const auto & [lat1, lon1] = std::make_tuple (p1.lat , p1.lon );
187
+
176
188
// Convert latitude and longitude to utm coordinates
177
189
const auto & [e0 , n0, zone0] = gpsToUTM (lat0, lon0);
178
190
const auto & [e1 , n1, zone1] = gpsToUTM (lat1, lon1);
179
- return {e1 - e0 , n1 - n0};
180
- }
181
191
182
- inline Eigen::Affine2f gpsToLocal (double current_lat, double current_lon,
183
- double current_heading, double goal_lat,
184
- double goal_lon, double goal_heading) {
185
- // Step 1: Convert current and goal GPS coordinates to UTM
186
- const auto & [curr_easting, curr_northing, curr_zone] =
187
- gpsToUTM (current_lat, current_lon);
188
- const auto & [goal_easting, goal_northing, goal_zone] =
189
- gpsToUTM (goal_lat, goal_lon);
190
- // Ensure that both coordinates are in the same UTM zone
191
- if (goal_zone != curr_zone) {
192
+ if (zone0 != zone1) {
192
193
throw std::runtime_error (" GPS points are in different UTM zones." );
193
194
}
194
195
195
- // Step 2: Calculate the translation vector from the current position to the
196
- // goal in UTM
197
- double dx = goal_easting - curr_easting;
198
- double dy = goal_northing - curr_northing;
196
+ return {e1 - e0 , n1 - n0}; // x y
197
+ }
198
+
199
+ inline Eigen::Affine2f gpsToLocal (const GPSPoint& current,
200
+ const GPSPoint& goal) {
201
+ // Step 1: Convert the GPS coordinates to global coordinates
202
+ const auto & dvec = gpsToGlobalCoord (current, goal);
199
203
200
- // Step 3 : Convert the current heading to radians and adjust for x-axis
204
+ // Step 2 : Convert the current heading to radians and adjust for x-axis
201
205
// reference Since 0 degrees points along the y-axis and rotates
202
206
// counter-clockwise, convert to radians with 0 degrees aligned along the
203
207
// x-axis
204
- double current_heading_rad = (90.0 - current_heading ) * M_PI / 180.0 ;
208
+ double current_heading_rad = (90.0 - current. heading ) * M_PI / 180.0 ;
205
209
206
- // Step 4 : Rotate the translation vector to the robot's local frame
207
- double local_x =
208
- dx * cos (-current_heading_rad) - dy * sin (-current_heading_rad);
209
- double local_y =
210
- dx * sin (-current_heading_rad) + dy * cos (-current_heading_rad);
210
+ // Step 3 : Rotate the translation vector to the robot's local frame
211
+ double local_x = dvec. x () * cos (-current_heading_rad) -
212
+ dvec. y () * sin (-current_heading_rad);
213
+ double local_y = dvec. x () * sin (-current_heading_rad) +
214
+ dvec. y () * cos (-current_heading_rad);
211
215
212
- // Step 5 : Convert the goal heading to the local frame
213
- double goal_heading_rad = (90.0 - goal_heading ) * M_PI / 180.0 ;
216
+ // Step 4 : Convert the goal heading to the local frame
217
+ double goal_heading_rad = (90.0 - goal. heading ) * M_PI / 180.0 ;
214
218
double local_heading = goal_heading_rad - current_heading_rad;
215
219
216
220
// Normalize local heading to the range [-pi, pi]
217
221
while (local_heading > M_PI) local_heading -= 2 * M_PI;
218
222
while (local_heading < -M_PI) local_heading += 2 * M_PI;
219
223
220
- // Step 6 : Create the affine transformation for the local pose of the goal
224
+ // Step 5 : Create the affine transformation for the local pose of the goal
221
225
Eigen::Affine2f transform = Eigen::Translation2f (local_x, local_y) *
222
226
Eigen::Rotation2Df (local_heading);
223
227
0 commit comments