Skip to content

Commit baf8141

Browse files
committed
[success]convert blh to enu
1 parent 89442db commit baf8141

6 files changed

+307
-282
lines changed

include/gnss_preprocessing_component.hpp

Lines changed: 0 additions & 48 deletions
This file was deleted.

include/gnss_preprocessing_core.hpp

Lines changed: 119 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,38 @@ using namespace std;
2121
class GnssPreprocessingCore
2222
{
2323
public:
24-
//GnssPreprocessingCore();
25-
//GnssPreprocessingCore(ros::NodeHandle &n);
26-
//GnssPreprocessingCore(double lat, double lon, double hig);
2724
GnssPreprocessingCore(ros::NodeHandle &n, double lat, double lon, double hig);
2825
~GnssPreprocessingCore();
2926

3027
double pi = 3.1415926535898;
3128
double a = 6378137.0;
3229
double ONE_F = 298.257223563;
3330
double E2 = ((1.0/ONE_F)*(2-(1.0/ONE_F)));
34-
35-
Eigen::Vector3d origin;
3631
private:
32+
// local variable
3733
ros::NodeHandle nh;
34+
double lat0;
35+
double lon0;
36+
double hig0;
3837

3938
// publisher
39+
ros::Publisher gnss_pose_pub;
40+
ros::Publisher gnss_path_pub;
4041

4142
// publish data
4243
nav_msgs::Path gnss_path;
4344

4445
// subscriber
4546
ros::Subscriber gnss_sub;
4647

48+
// tf publish
49+
tf::TransformBroadcaster odom_to_baselink_broadcaster;
50+
geometry_msgs::TransformStamped odom_to_baselink_trans;
51+
4752
// callback function
4853
void gnssCallback(const sensor_msgs::NavSatFixConstPtr& gnss_msg);
4954

55+
// convert (lat, lon, alt) to (x, y, z)
5056
double deg2rad(double deg); // Convert degrees to radians
5157
double rad2deg(double rad); // Convert radians to degrees
5258
Eigen::Vector3d blh2ecef(double p_deg, double l_deg, double h);
@@ -55,6 +61,10 @@ class GnssPreprocessingCore
5561
Eigen::Matrix3d rotx(double theta);
5662
Eigen::Matrix3d roty(double theta);
5763
Eigen::Matrix3d rotz(double theta);
64+
65+
// different version convert (lat, lon, alt) to (x, y, z)
66+
int blh2enu(double lat0, double lon0, double lat, double lon, double *x, double *y);
67+
double constrain(double val, double min, double max);
5868
};
5969

6070
/***********************************************************************
@@ -64,20 +74,16 @@ GnssPreprocessingCore::GnssPreprocessingCore(ros::NodeHandle &n, double lat, dou
6474
{
6575
std::cout << "GnssPreprocessingCore Start!" << std::endl;
6676

67-
std::cout << lat << std::endl;
68-
std::cout << lon << std::endl;
69-
std::cout << hig << std::endl;
70-
71-
// ROS Node
77+
// init local variable
7278
nh = n;
7379

74-
origin(0) = lat;
75-
origin(1) = lon;
76-
origin(2) = hig;
80+
lat0 = lat;
81+
lon0 = lon;
82+
hig0 = hig;
7783

7884
// Publisher
79-
//gnss_pose_pub = nh.advertise<geometry_msgs::PoseStamped>("/gnss_pose", 10);
80-
//gnss_path_pub = nh.advertise<nav_msgs::Path>("/gnss_path", 10);
85+
gnss_pose_pub = nh.advertise<geometry_msgs::PoseStamped>("/gnss_pose", 10);
86+
gnss_path_pub = nh.advertise<nav_msgs::Path>("/gnss_path", 10);
8187

8288
// Subscriber
8389
gnss_sub = nh.subscribe("/fix", 10, &GnssPreprocessingCore::gnssCallback, this);
@@ -95,93 +101,96 @@ GnssPreprocessingCore::~GnssPreprocessingCore()
95101

96102
void GnssPreprocessingCore::gnssCallback(const sensor_msgs::NavSatFixConstPtr& gnss_msg)
97103
{
98-
/*
99-
std::cout << gnss_msg->latitude << std::endl;
100-
std::cout << gnss_msg->longitude << std::endl;
101-
std::cout << gnss_msg->altitude << std::endl;
102-
*/
103-
104-
/*
105-
std::cout << origin(0) << std::endl;
106-
std::cout << origin(1) << std::endl;
107-
std::cout << origin(2) << std::endl;
108-
*/
109-
110104
// Convert lat/lon/height to ECEF
111-
Eigen::Vector3d ecef_origin = blh2ecef(origin(0), origin(1), origin(2));
112-
/*
113-
std::cout << ecef_origin(0) << std::endl;
114-
std::cout << ecef_origin(1) << std::endl;
115-
std::cout << ecef_origin(2) << std::endl;
116-
*/
105+
/***********************************************************************
106+
NED座標系になっている可能性がある -> enu
107+
enu[0] = N
108+
enu[1] = E
109+
enu[2] = D
110+
となっている可能性があるので、publishする際は現状
111+
X = E = enu[1]
112+
Y = N = enu[0]
113+
としている。
114+
**********************************************************************/
115+
Eigen::Vector3d ecef_origin = blh2ecef(lat0, lon0, hig0);
117116
Eigen::Vector3d ecef = blh2ecef(gnss_msg->latitude, gnss_msg->longitude, gnss_msg->altitude);
118-
119117
Eigen::Vector3d enu = ecef2enu(ecef, ecef_origin);
120-
/*
121-
std::cout << enu(0) << std::endl;
122-
std::cout << enu(1) << std::endl;
123-
std::cout << enu(2) << std::endl;
124-
*/
125118

119+
/***********************************************************************
120+
こちらの処理の場合は正常にENU座標値が算出される
121+
enu[0] = E
122+
enu[1] = N
123+
enu[2] = U
124+
publishする際は
125+
X = E = enu[0]
126+
Y = N = enu[1]
127+
とする。
128+
**********************************************************************/
126129
/*
127-
data_conversion_gps(gps_msg, gps_data);
128-
130+
double x, y;
131+
blh2enu(lat0, lon0, gnss_msg->latitude, gnss_msg->longitude, &x, &y);
132+
Eigen::Vector3d enu = Eigen::Vector3d(x, y, gnss_msg->altitude);
133+
*/
134+
129135
geometry_msgs::PoseStamped point;
130136
point.header.frame_id = "map";
131137
point.header.stamp = ros::Time::now();
132-
point.pose.position.x = gps_data.ned[0];
133-
point.pose.position.y = gps_data.ned[1];
138+
point.pose.position.x = enu[1];
139+
point.pose.position.y = enu[0];
134140
point.pose.position.z = 0.0;
135141
point.pose.orientation.w = 0;
136142
point.pose.orientation.x = 0;
137143
point.pose.orientation.y = 0;
138144
point.pose.orientation.z = 1.0;
139-
gps_path.poses.push_back(point);
140-
gps_pose_pub.publish(point);
141-
gps_path_pub.publish(gps_path);
145+
146+
gnss_path.poses.push_back(point);
147+
gnss_pose_pub.publish(point);
148+
gnss_path_pub.publish(gnss_path);
142149

143150
// /odom to /base_link transform broadcast
144151
odom_to_baselink_trans.header.stamp = ros::Time::now();
145152
odom_to_baselink_trans.header.frame_id = "odom";
146153
odom_to_baselink_trans.child_frame_id = "base_link";
147-
odom_to_baselink_trans.transform.translation.x = gps_data.ned[0];
148-
odom_to_baselink_trans.transform.translation.y = gps_data.ned[1];
154+
odom_to_baselink_trans.transform.translation.x = enu[1];
155+
odom_to_baselink_trans.transform.translation.y = enu[0];
149156
odom_to_baselink_trans.transform.translation.z = 0.0;
150157
odom_to_baselink_trans.transform.rotation.x = 0.0;
151158
odom_to_baselink_trans.transform.rotation.y = 0.0;
152159
odom_to_baselink_trans.transform.rotation.z = 0.0;
153160
odom_to_baselink_trans.transform.rotation.w = 1.0;
154161
odom_to_baselink_broadcaster.sendTransform(odom_to_baselink_trans);
155-
*/
156162
}
157163

164+
/***********************************************************************
165+
* Convert (lat, lon, alt) -> (x, y, z)
166+
**********************************************************************/
158167
Eigen::Vector3d GnssPreprocessingCore::blh2ecef(double p_deg, double l_deg, double h) {
159168
double p_rad = deg2rad(p_deg);
160169
double l_rad = deg2rad(l_deg);
161170

162-
double NN = (a / sqrt(1.0 - (E2)*pow(sin(p_rad),2)));
171+
double N = (a / sqrt(1.0 - E2 * pow(sin(p_rad), 2)));
163172

164-
double x = (NN+h)*cos(p_rad)*cos(l_rad);
165-
double y = (NN+h)*cos(p_rad)*sin(l_rad);
166-
double z = (NN*(1-E2)+h)*sin(p_rad);
173+
double x = (N + h) * cos(p_rad) * cos(l_rad);
174+
double y = (N + h) * cos(p_rad) * sin(l_rad);
175+
double z = (N * (1 - E2) + h) * sin(p_rad);
167176

168177
return Eigen::Vector3d(x, y, z);
169178
}
170179

171180
Eigen::Vector3d GnssPreprocessingCore::ecef2blh(double x, double y, double z) {
172-
double b = (a*(1.0 - 1.0/ONE_F));
173-
double ED2 = (E2*pow(a,2)/(pow(b,2)));
174-
double p = sqrt(pow(x,2) + pow(y,2));
175-
double si = atan2(z*a, p*b);
181+
double b = (a * (1.0 - 1.0 / ONE_F));
182+
double ED2 = (E2 * pow(a, 2) / (pow(b, 2)));
183+
double p = sqrt(pow(x, 2) + pow(y, 2));
184+
double si = atan2(z * a, p * b);
176185

177-
double p_rad2 = atan2((z + ED2*b*pow(sin(si),3)),(p-E2*a*pow(cos(si),3)));
186+
double p_rad2 = atan2((z + ED2 * b * pow(sin(si), 3)), (p - E2 * a * pow(cos(si), 3)));
178187
double l_rad2 = atan2(y, x);
179188

180189
double lat = rad2deg(p_rad2);
181190
double lon = rad2deg(l_rad2);
182191

183-
double NN = (a / sqrt(1.0 - (E2)*pow(sin(p_rad2),2)));
184-
double hig = (p/cos(p_rad2)) - NN;
192+
double N = (a / sqrt(1.0 - E2 * pow(sin(p_rad2), 2)));
193+
double hig = (p / cos(p_rad2)) - N;
185194

186195
return Eigen::Vector3d(lat, lon, hig);
187196
}
@@ -190,14 +199,15 @@ Eigen::Vector3d GnssPreprocessingCore::ecef2enu(Eigen::Vector3d dest, Eigen::Vec
190199
Eigen::Vector3d blh = ecef2blh(origin(0), origin(1), origin(2));
191200

192201
Eigen::Matrix3d rotzp1 = rotz(90.0);
193-
Eigen::Matrix3d rotyp = roty(90.0-blh(0));
202+
Eigen::Matrix3d rotyp = roty(90.0 - blh(0));
194203
Eigen::Matrix3d rotzp2 = rotz(blh(1));
195204

196-
Eigen::Matrix3d mat_conv1 = rotzp1*rotyp;
197-
Eigen::Matrix3d mat_conv2 = mat_conv1*rotzp2;
205+
Eigen::Matrix3d mat_conv1 = rotzp1 * rotyp;
206+
Eigen::Matrix3d mat_conv2 = mat_conv1 * rotzp2;
198207

199208
Eigen::Vector3d mov = dest - origin;
200-
return mat_conv2*mov;
209+
210+
return mat_conv2 * mov;
201211
}
202212

203213
Eigen::Matrix3d GnssPreprocessingCore::rotx(double theta) {
@@ -240,4 +250,49 @@ double GnssPreprocessingCore::rad2deg(double rad) {
240250
return rad * 180.0 / pi;
241251
}
242252

253+
/***********************************************************************
254+
* Convert (lat, lon, alt) -> (x, y, z)
255+
**********************************************************************/
256+
int GnssPreprocessingCore::blh2enu(double lat0, double lon0, double lat, double lon, double *x, double *y)
257+
{
258+
static constexpr double CONSTANTS_RADIUS_OF_EARTH = 6371000; //[m]
259+
260+
const double lat0_rad = lat0 * (M_PI / 180.0);
261+
const double lon0_rad = lon0 * (M_PI / 180.0);
262+
const double lat_rad = lat * (M_PI / 180.0);
263+
const double lon_rad = lon * (M_PI / 180.0);
264+
265+
const double sin_lat0 = sin(lat0_rad);
266+
const double cos_lat0 = cos(lat0_rad);
267+
const double sin_lat = sin(lat_rad);
268+
const double cos_lat = cos(lat_rad);
269+
270+
const double cos_d_lon = cos(lon_rad - lon0_rad);
271+
272+
const double arg = constrain(sin_lat0 * sin_lat + cos_lat0 * cos_lat * cos_d_lon, -1.0, 1.0);
273+
const double c = acos(arg);
274+
275+
double k = 1.0;
276+
277+
if (fabs(c) > 0) {
278+
k = (c / sin(c));
279+
}
280+
281+
*x = static_cast<double>(k * (cos_lat0 * sin_lat - sin_lat0 * cos_lat * cos_d_lon) * CONSTANTS_RADIUS_OF_EARTH);
282+
*y = static_cast<double>(k * cos_lat * sin(lon_rad - lon0_rad) * CONSTANTS_RADIUS_OF_EARTH);
283+
284+
return 0;
285+
}
286+
287+
double GnssPreprocessingCore::constrain(double val, double min, double max)
288+
{
289+
if (val > max) {
290+
return max;
291+
} else if (val < min) {
292+
return min;
293+
} else {
294+
return val;
295+
}
296+
}
297+
243298
#endif // __GNSS_PREPROCESSING_CORE_HPP__

launch/gnss_preprocessing.launch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
<!--rosbag play-->
1010
<node pkg="rosbag" type="play" name="player" output="screen" args="--clock /home/ramune/Downloads/utbm_robocar_dataset_20190131_noimage.bag"/>
1111
<!--display rviz-->
12-
<!--<node name="rviz" pkg="rviz" type="rviz" args="-d $(find gnss_imu_odom_ESKF)/rviz/gps_trajectory_plotter.rviz" required="true"/>-->
12+
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find gnss_preprocessing)/rviz/gnss_preprocessing.rviz" required="true"/>
1313
</launch>

0 commit comments

Comments
 (0)