@@ -21,32 +21,38 @@ using namespace std;
21
21
class GnssPreprocessingCore
22
22
{
23
23
public:
24
- // GnssPreprocessingCore();
25
- // GnssPreprocessingCore(ros::NodeHandle &n);
26
- // GnssPreprocessingCore(double lat, double lon, double hig);
27
24
GnssPreprocessingCore (ros::NodeHandle &n, double lat, double lon, double hig);
28
25
~GnssPreprocessingCore ();
29
26
30
27
double pi = 3.1415926535898 ;
31
28
double a = 6378137.0 ;
32
29
double ONE_F = 298.257223563 ;
33
30
double E2 = ((1.0 /ONE_F)*(2 -(1.0 /ONE_F)));
34
-
35
- Eigen::Vector3d origin;
36
31
private:
32
+ // local variable
37
33
ros::NodeHandle nh;
34
+ double lat0;
35
+ double lon0;
36
+ double hig0;
38
37
39
38
// publisher
39
+ ros::Publisher gnss_pose_pub;
40
+ ros::Publisher gnss_path_pub;
40
41
41
42
// publish data
42
43
nav_msgs::Path gnss_path;
43
44
44
45
// subscriber
45
46
ros::Subscriber gnss_sub;
46
47
48
+ // tf publish
49
+ tf::TransformBroadcaster odom_to_baselink_broadcaster;
50
+ geometry_msgs::TransformStamped odom_to_baselink_trans;
51
+
47
52
// callback function
48
53
void gnssCallback (const sensor_msgs::NavSatFixConstPtr& gnss_msg);
49
54
55
+ // convert (lat, lon, alt) to (x, y, z)
50
56
double deg2rad (double deg); // Convert degrees to radians
51
57
double rad2deg (double rad); // Convert radians to degrees
52
58
Eigen::Vector3d blh2ecef (double p_deg, double l_deg, double h);
@@ -55,6 +61,10 @@ class GnssPreprocessingCore
55
61
Eigen::Matrix3d rotx (double theta);
56
62
Eigen::Matrix3d roty (double theta);
57
63
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);
58
68
};
59
69
60
70
/* **********************************************************************
@@ -64,20 +74,16 @@ GnssPreprocessingCore::GnssPreprocessingCore(ros::NodeHandle &n, double lat, dou
64
74
{
65
75
std::cout << " GnssPreprocessingCore Start!" << std::endl;
66
76
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
72
78
nh = n;
73
79
74
- origin ( 0 ) = lat;
75
- origin ( 1 ) = lon;
76
- origin ( 2 ) = hig;
80
+ lat0 = lat;
81
+ lon0 = lon;
82
+ hig0 = hig;
77
83
78
84
// 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 );
81
87
82
88
// Subscriber
83
89
gnss_sub = nh.subscribe (" /fix" , 10 , &GnssPreprocessingCore::gnssCallback, this );
@@ -95,93 +101,96 @@ GnssPreprocessingCore::~GnssPreprocessingCore()
95
101
96
102
void GnssPreprocessingCore::gnssCallback (const sensor_msgs::NavSatFixConstPtr& gnss_msg)
97
103
{
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
-
110
104
// 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);
117
116
Eigen::Vector3d ecef = blh2ecef (gnss_msg->latitude , gnss_msg->longitude , gnss_msg->altitude );
118
-
119
117
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
- */
125
118
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
+ **********************************************************************/
126
129
/*
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
+
129
135
geometry_msgs::PoseStamped point;
130
136
point.header .frame_id = " map" ;
131
137
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 ];
134
140
point.pose .position .z = 0.0 ;
135
141
point.pose .orientation .w = 0 ;
136
142
point.pose .orientation .x = 0 ;
137
143
point.pose .orientation .y = 0 ;
138
144
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);
142
149
143
150
// /odom to /base_link transform broadcast
144
151
odom_to_baselink_trans.header .stamp = ros::Time::now ();
145
152
odom_to_baselink_trans.header .frame_id = " odom" ;
146
153
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 ];
149
156
odom_to_baselink_trans.transform .translation .z = 0.0 ;
150
157
odom_to_baselink_trans.transform .rotation .x = 0.0 ;
151
158
odom_to_baselink_trans.transform .rotation .y = 0.0 ;
152
159
odom_to_baselink_trans.transform .rotation .z = 0.0 ;
153
160
odom_to_baselink_trans.transform .rotation .w = 1.0 ;
154
161
odom_to_baselink_broadcaster.sendTransform (odom_to_baselink_trans);
155
- */
156
162
}
157
163
164
+ /* **********************************************************************
165
+ * Convert (lat, lon, alt) -> (x, y, z)
166
+ **********************************************************************/
158
167
Eigen::Vector3d GnssPreprocessingCore::blh2ecef (double p_deg, double l_deg, double h) {
159
168
double p_rad = deg2rad (p_deg);
160
169
double l_rad = deg2rad (l_deg);
161
170
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 )));
163
172
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);
167
176
168
177
return Eigen::Vector3d (x, y, z);
169
178
}
170
179
171
180
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);
176
185
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 )));
178
187
double l_rad2 = atan2 (y, x);
179
188
180
189
double lat = rad2deg (p_rad2);
181
190
double lon = rad2deg (l_rad2);
182
191
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 ;
185
194
186
195
return Eigen::Vector3d (lat, lon, hig);
187
196
}
@@ -190,14 +199,15 @@ Eigen::Vector3d GnssPreprocessingCore::ecef2enu(Eigen::Vector3d dest, Eigen::Vec
190
199
Eigen::Vector3d blh = ecef2blh (origin (0 ), origin (1 ), origin (2 ));
191
200
192
201
Eigen::Matrix3d rotzp1 = rotz (90.0 );
193
- Eigen::Matrix3d rotyp = roty (90.0 - blh (0 ));
202
+ Eigen::Matrix3d rotyp = roty (90.0 - blh (0 ));
194
203
Eigen::Matrix3d rotzp2 = rotz (blh (1 ));
195
204
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;
198
207
199
208
Eigen::Vector3d mov = dest - origin;
200
- return mat_conv2*mov;
209
+
210
+ return mat_conv2 * mov;
201
211
}
202
212
203
213
Eigen::Matrix3d GnssPreprocessingCore::rotx (double theta) {
@@ -240,4 +250,49 @@ double GnssPreprocessingCore::rad2deg(double rad) {
240
250
return rad * 180.0 / pi ;
241
251
}
242
252
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
+
243
298
#endif // __GNSS_PREPROCESSING_CORE_HPP__
0 commit comments