Skip to content

Commit 1966da7

Browse files
committed
Refactored gps translator for gps to map conversion option
1 parent 0d47c47 commit 1966da7

File tree

1 file changed

+62
-95
lines changed

1 file changed

+62
-95
lines changed

math/gps_util.h

+62-95
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "shared/math/math_util.h"
1212
#include "shared/util/helpers.h"
1313

14+
using Eigen::Affine2d;
1415
using Eigen::Rotation2Dd;
1516
using Eigen::Vector2d;
1617
using math_util::AngleMod;
@@ -40,76 +41,6 @@ struct GPSPoint {
4041
double heading; // True North (degrees)
4142
};
4243

43-
struct GPSTranslator {
44-
GPSTranslator() : is_origin_set(false) {}
45-
46-
string GetMapFileFromName(const string& maps_dir, const string& map) {
47-
return maps_dir + "/" + map + "/" + map + ".gpsmap.txt";
48-
}
49-
50-
bool Load(const string& maps_dir, const string& map) {
51-
const string file = GetMapFileFromName(maps_dir, map);
52-
ScopedFile fid(file, "r", true);
53-
if (fid() == nullptr) return false;
54-
if (fscanf(fid(), "%lf, %lf, %lf", &gps_origin_latitude,
55-
&gps_origin_longitude, &map_orientation) != 3) {
56-
return false;
57-
}
58-
printf("Map origin: %12.8lf, %12.8lf\n", gps_origin_latitude,
59-
gps_origin_longitude);
60-
is_origin_set = true;
61-
return true;
62-
}
63-
64-
void SetOrigin(double latitude, double longitude, double orientation) {
65-
gps_origin_latitude = latitude;
66-
gps_origin_longitude = longitude;
67-
map_orientation = orientation;
68-
is_origin_set = true;
69-
}
70-
71-
Vector2d GPSToMetric(const double latitude, const double longitude) {
72-
CHECK(is_origin_set);
73-
const double theta = DegToRad(latitude);
74-
const double c = std::cos(theta);
75-
const double s = std::sin(theta);
76-
const double r =
77-
sqrt(Sq(wgs_84_a * wgs_84_b) / (Sq(c * wgs_84_b) + Sq(s * wgs_84_a)));
78-
const double dlat = DegToRad(latitude - gps_origin_latitude);
79-
const double dlong = DegToRad(longitude - gps_origin_longitude);
80-
const double r1 = r * c;
81-
const double x = r1 * dlong;
82-
const double y = r * dlat;
83-
return Rotation2Dd(map_orientation) * Vector2d(x, y);
84-
}
85-
86-
void MetricToGPS(const Vector2d& loc, double* longitude, double* latitude) {
87-
CHECK(is_origin_set);
88-
const double theta = DegToRad(gps_origin_latitude);
89-
const double c = std::cos(theta);
90-
const double s = std::sin(theta);
91-
const double r =
92-
sqrt(Sq(wgs_84_a * wgs_84_b) / (Sq(c * wgs_84_b) + Sq(s * wgs_84_a)));
93-
const double r1 = r * c;
94-
const double dlat = loc.y() / r;
95-
const double dlong = loc.x() / r1;
96-
*longitude = gps_origin_longitude + dlong;
97-
*latitude = gps_origin_latitude + dlat;
98-
}
99-
100-
double gps_origin_longitude;
101-
double gps_origin_latitude;
102-
double map_orientation;
103-
bool is_origin_set;
104-
105-
// Earth geoid parameters from WGS 84 system
106-
// https://en.wikipedia.org/wiki/World_Geodetic_System#A_new_World_Geodetic_System:_WGS_84
107-
// a = Semimajor (Equatorial) axis
108-
static constexpr double wgs_84_a = 6378137.0;
109-
// b = Semiminor (Polar) axis
110-
static constexpr double wgs_84_b = 6356752.314245;
111-
};
112-
11344
inline std::tuple<double, double, int> gpsToUTM(double lat, double lon) {
11445
// Constants for UTM conversion
11546
constexpr double a = 6378137.0; // WGS-84 major axis
@@ -203,37 +134,73 @@ inline double gpsToGlobalHeading(const GPSPoint& p0) {
203134
return AngleMod(heading);
204135
}
205136

206-
inline Eigen::Affine2f gpsToLocal(const GPSPoint& current,
207-
const GPSPoint& goal) {
208-
// Step 1: Convert the GPS coordinates to global coordinates
209-
const auto& dvec = gpsToGlobalCoord(current, goal);
137+
struct GPSTranslator {
138+
// Convenience wrapper for GPS to map coordinate transformations
139+
GPSTranslator()
140+
: is_gps_origin_set(false),
141+
is_map_origin_set(false),
142+
use_map_as_origin(false) {}
143+
144+
bool Initialized() const { return is_gps_origin_set && is_map_origin_set; }
145+
146+
void SetReferenceFrame(const string& frame) {
147+
if (frame == "map") {
148+
use_map_as_origin = true;
149+
} else if (frame == "utm") {
150+
use_map_as_origin = false;
151+
} else {
152+
throw std::runtime_error("Invalid reference frame.");
153+
}
154+
}
210155

211-
// Step 2: Convert the current heading to radians and adjust for x-axis
212-
// reference Since 0 degrees pogpsToGlobalHeadingints along the y-axis and
213-
// rotates counter-clockwise, convert to radians with 0 degrees aligned along
214-
// the x-axis
215-
double current_heading_rad = (90.0 - current.heading) * M_PI / 180.0;
156+
void SetGPSOrigin(const GPSPoint& p) {
157+
gps_origin = p;
158+
is_gps_origin_set = true;
159+
T_initial_gps = Eigen::Affine2d::Identity();
160+
}
216161

217-
// Step 3: Rotate the translation vector to the robot's local frame
218-
double local_x = dvec.x() * cos(-current_heading_rad) -
219-
dvec.y() * sin(-current_heading_rad);
220-
double local_y = dvec.x() * sin(-current_heading_rad) +
221-
dvec.y() * cos(-current_heading_rad);
162+
void SetMapOrigin(const Affine2d& p) {
163+
T_initial_map = p;
164+
is_map_origin_set = true;
165+
}
166+
167+
Eigen::Vector2d GpsToGlobalCoord(const GPSPoint& p1) {
168+
if (!is_gps_origin_set || !is_map_origin_set) {
169+
throw std::runtime_error("GPS or map origin not set.");
170+
}
222171

223-
// Step 4: Convert the goal heading to the local frame
224-
double goal_heading_rad = (90.0 - goal.heading) * M_PI / 180.0;
225-
double local_heading = goal_heading_rad - current_heading_rad;
172+
Eigen::Vector2d gps_loc = gpsToGlobalCoord(gps_origin, p1);
173+
Eigen::Affine2d T_base_gps = Eigen::Rotation2Dd(gpsToGlobalHeading(p1)) *
174+
Eigen::Translation2d(gps_loc);
175+
if (use_map_as_origin) {
176+
Eigen::Affine2d T_gps_map = T_initial_gps * T_initial_map.inverse();
177+
return (T_gps_map * T_base_gps).translation();
178+
}
226179

227-
// Normalize local heading to the range [-pi, pi]
228-
while (local_heading > M_PI) local_heading -= 2 * M_PI;
229-
while (local_heading < -M_PI) local_heading += 2 * M_PI;
180+
return gps_loc;
181+
}
230182

231-
// Step 5: Create the affine transformation for the local pose of the goal
232-
Eigen::Affine2f transform = Eigen::Translation2f(local_x, local_y) *
233-
Eigen::Rotation2Df(local_heading);
183+
double GpsToGlobalHeading(const GPSPoint& p0) {
184+
if (!is_gps_origin_set || !is_map_origin_set) {
185+
throw std::runtime_error("GPS or map origin not set.");
186+
}
187+
double heading_global = gpsToGlobalHeading(p0);
188+
if (use_map_as_origin) {
189+
Eigen::Affine2d T_gps_map = T_initial_gps * T_initial_map.inverse();
190+
Eigen::Rotation2Dd R_base_gps = Eigen::Rotation2Dd(heading_global);
191+
Eigen::Rotation2Dd R_gps_map(T_gps_map.linear());
192+
return (R_gps_map * R_base_gps).angle();
193+
}
194+
return heading_global;
195+
}
234196

235-
return transform;
236-
}
197+
bool is_gps_origin_set;
198+
bool is_map_origin_set;
199+
bool use_map_as_origin;
200+
GPSPoint gps_origin;
201+
Affine2d T_initial_gps;
202+
Affine2d T_initial_map;
203+
};
237204

238205
} // namespace gps_util
239206

0 commit comments

Comments
 (0)