18
18
#include " ekf_localizer/string.hpp"
19
19
#include " ekf_localizer/warning_message.hpp"
20
20
#include " localization_util/covariance_ellipse.hpp"
21
+ #include " tf2/LinearMath/Quaternion.h"
21
22
22
23
#include < autoware/universe_utils/geometry/geometry.hpp>
23
24
#include < autoware/universe_utils/math/unit_conversion.hpp>
24
25
#include < autoware/universe_utils/ros/msg_covariance.hpp>
25
26
#include < rclcpp/duration.hpp>
26
27
#include < rclcpp/logging.hpp>
27
28
29
+ #include " tf2_geometry_msgs/tf2_geometry_msgs/tf2_geometry_msgs.hpp"
30
+
28
31
#include < fmt/core.h>
29
32
30
33
#include < algorithm>
@@ -87,6 +90,12 @@ EKFLocalizer::EKFLocalizer(const rclcpp::NodeOptions & node_options)
87
90
sub_twist_with_cov_ = create_subscription<geometry_msgs::msg::TwistWithCovarianceStamped>(
88
91
" in_twist_with_covariance" , 1 ,
89
92
std::bind (&EKFLocalizer::callback_twist_with_covariance, this , _1));
93
+ if (params_.use_imu ) {
94
+ sub_imu_ = create_subscription<sensor_msgs::msg::Imu>(
95
+ " /sensing/gnss/sbg/ros/imu/data" , 1 , std::bind (&EKFLocalizer::callback_imu, this , _1));
96
+ tf_buffer_ = std::make_shared<tf2_ros::Buffer>(this ->get_clock ());
97
+ tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
98
+ }
90
99
service_trigger_node_ = create_service<std_srvs::srv::SetBool>(
91
100
" trigger_node_srv" ,
92
101
std::bind (
@@ -102,6 +111,8 @@ EKFLocalizer::EKFLocalizer(const rclcpp::NodeOptions & node_options)
102
111
z_filter_.set_proc_dev (params_.z_filter_proc_dev );
103
112
roll_filter_.set_proc_dev (params_.roll_filter_proc_dev );
104
113
pitch_filter_.set_proc_dev (params_.pitch_filter_proc_dev );
114
+
115
+ std::cout << " *********************** use_imu: " << params_.use_imu << std::endl;
105
116
}
106
117
107
118
/*
@@ -230,13 +241,12 @@ void EKFLocalizer::timer_callback()
230
241
}
231
242
twist_diag_info_.no_update_count = twist_is_updated ? 0 : (twist_diag_info_.no_update_count + 1 );
232
243
233
- const double z = z_filter_.get_x ();
234
- const double roll = roll_filter_.get_x ();
235
- const double pitch = pitch_filter_.get_x ();
236
- const geometry_msgs::msg::PoseStamped current_ekf_pose =
237
- ekf_module_->get_current_pose (current_time, z, roll, pitch, false );
238
- const geometry_msgs::msg::PoseStamped current_biased_ekf_pose =
239
- ekf_module_->get_current_pose (current_time, z, roll, pitch, true );
244
+ RollPitchHeightStruct roll_pitch_height = get_roll_pitch_height (current_time);
245
+
246
+ const geometry_msgs::msg::PoseStamped current_ekf_pose = ekf_module_->get_current_pose (
247
+ current_time, roll_pitch_height.z , roll_pitch_height.roll , roll_pitch_height.pitch , false );
248
+ const geometry_msgs::msg::PoseStamped current_biased_ekf_pose = ekf_module_->get_current_pose (
249
+ current_time, roll_pitch_height.z , roll_pitch_height.roll , roll_pitch_height.pitch , true );
240
250
const geometry_msgs::msg::TwistStamped current_ekf_twist =
241
251
ekf_module_->get_current_twist (current_time);
242
252
@@ -245,6 +255,53 @@ void EKFLocalizer::timer_callback()
245
255
publish_diagnostics (current_ekf_pose, current_time);
246
256
}
247
257
258
+ /*
259
+ * find_closest_imu_msg
260
+ */
261
+ sensor_msgs::msg::Imu EKFLocalizer::find_closest_imu_msg (const rclcpp::Time & current_time)
262
+ {
263
+ sensor_msgs::msg::Imu closest_imu_msg;
264
+ uint64_t min_time_diff = std::numeric_limits<uint64_t >::max ();
265
+ const int64_t pose_time_ns = current_time.nanoseconds ();
266
+
267
+ for (const auto & imu_msg : imu_msg_deque_) {
268
+ const int64_t imu_time_ns = imu_msg.header .stamp .sec * 1e9 + imu_msg.header .stamp .nanosec ;
269
+ uint64_t time_diff = std::abs (pose_time_ns - imu_time_ns);
270
+ if (time_diff < min_time_diff) {
271
+ min_time_diff = time_diff;
272
+ closest_imu_msg = imu_msg;
273
+ }
274
+ }
275
+ return closest_imu_msg;
276
+ }
277
+
278
+ /*
279
+ * get_roll_pitch_height
280
+ */
281
+ EKFLocalizer::RollPitchHeightStruct EKFLocalizer::get_roll_pitch_height (
282
+ const rclcpp::Time current_time)
283
+ {
284
+ RollPitchHeightStruct roll_pitch_height;
285
+
286
+ if (params_.use_imu && !imu_msg_deque_.empty () && imu_dt_ > 0.0 ) { // ???
287
+ sensor_msgs::msg::Imu new_imu_msg = find_closest_imu_msg (current_time);
288
+ roll_pitch_height.z =
289
+ z_filter_.get_x () + new_imu_msg.linear_acceleration .z * imu_dt_ * imu_dt_ / 2.0 ;
290
+ const auto rpy = autoware::universe_utils::getRPY (new_imu_msg.orientation );
291
+ roll_pitch_height.roll = rpy.x ;
292
+ roll_pitch_height.pitch = rpy.y ;
293
+ } else {
294
+ if (params_.use_imu && imu_msg_deque_.empty ()) {
295
+ RCLCPP_WARN (this ->get_logger (), " IMU data is expected but the deque is empty." );
296
+ }
297
+ roll_pitch_height.z = z_filter_.get_x ();
298
+ roll_pitch_height.roll = roll_filter_.get_x ();
299
+ roll_pitch_height.pitch = pitch_filter_.get_x ();
300
+ }
301
+
302
+ return roll_pitch_height;
303
+ }
304
+
248
305
/*
249
306
* timer_tf_callback
250
307
*/
@@ -258,15 +315,15 @@ void EKFLocalizer::timer_tf_callback()
258
315
return ;
259
316
}
260
317
261
- const double z = z_filter_.get_x ();
262
- const double roll = roll_filter_.get_x ();
263
- const double pitch = pitch_filter_.get_x ();
264
-
265
318
const rclcpp::Time current_time = this ->now ();
266
319
320
+ RollPitchHeightStruct roll_pitch_height = get_roll_pitch_height (current_time);
321
+
267
322
geometry_msgs::msg::TransformStamped transform_stamped;
268
323
transform_stamped = autoware::universe_utils::pose2transform (
269
- ekf_module_->get_current_pose (current_time, z, roll, pitch, false ), " base_link" );
324
+ ekf_module_->get_current_pose (
325
+ current_time, roll_pitch_height.z , roll_pitch_height.roll , roll_pitch_height.pitch , false ),
326
+ " base_link" );
270
327
transform_stamped.header .stamp = current_time;
271
328
tf_br_->sendTransform (transform_stamped);
272
329
}
@@ -340,6 +397,51 @@ void EKFLocalizer::callback_twist_with_covariance(
340
397
twist_queue_.push (msg);
341
398
}
342
399
400
+ /*
401
+ * callback_imu
402
+ */
403
+ void EKFLocalizer::callback_imu (sensor_msgs::msg::Imu::SharedPtr msg)
404
+ {
405
+ sensor_msgs::msg::Imu imu_data = *msg;
406
+
407
+ geometry_msgs::msg::TransformStamped imu_to_base_link_transform;
408
+ try {
409
+ imu_to_base_link_transform =
410
+ tf_buffer_->lookupTransform (" base_link" , imu_data.header .frame_id , tf2::TimePointZero);
411
+ } catch (tf2::TransformException & ex) {
412
+ RCLCPP_WARN (this ->get_logger (), " Transform Error: %s" , ex.what ());
413
+ return ;
414
+ }
415
+
416
+ tf2::Quaternion imu_quat;
417
+ tf2::fromMsg (imu_data.orientation , imu_quat);
418
+
419
+ tf2::Quaternion transformed_quat = tf2::Transform (tf2::Quaternion (
420
+ imu_to_base_link_transform.transform .rotation .x ,
421
+ imu_to_base_link_transform.transform .rotation .y ,
422
+ imu_to_base_link_transform.transform .rotation .z ,
423
+ imu_to_base_link_transform.transform .rotation .w )) *
424
+ imu_quat;
425
+
426
+ geometry_msgs::msg::Quaternion new_orientation = tf2::toMsg (transformed_quat);
427
+
428
+ sensor_msgs::msg::Imu new_imu_msg;
429
+ new_imu_msg = imu_data;
430
+ new_imu_msg.orientation = new_orientation;
431
+ imu_msg_deque_.push_back (new_imu_msg);
432
+
433
+ while (imu_msg_deque_.size () > 15 ) {
434
+ imu_msg_deque_.pop_front ();
435
+ }
436
+ if (start == 1 ) {
437
+ imu_dt_ = std::abs ((last_imu_time_ - msg->header .stamp ).seconds ());
438
+ start = 0 ;
439
+ }
440
+ start = 1 ;
441
+
442
+ last_imu_time_ = msg->header .stamp ;
443
+ }
444
+
343
445
/*
344
446
* publish_estimate_result
345
447
*/
0 commit comments