@@ -37,6 +37,8 @@ using namespace std::placeholders;
3737ImuFilterMadgwickRos::ImuFilterMadgwickRos (const rclcpp::NodeOptions &options)
3838 : BaseNode(" imu_filter_madgwick" , options),
3939 tf_broadcaster_(*this ),
40+ tf_buffer_(this ->get_clock ()),
41+ tf_listener_(tf_buffer_),
4042 initialized_(false )
4143{
4244 RCLCPP_INFO (get_logger (), " Starting ImuFilter" );
@@ -61,6 +63,12 @@ ImuFilterMadgwickRos::ImuFilterMadgwickRos(const rclcpp::NodeOptions &options)
6163 declare_parameter (" publish_debug_topics" , false , descriptor);
6264 get_parameter (" publish_debug_topics" , publish_debug_topics_);
6365
66+ double time_jump_threshold = 0.0 ;
67+ declare_parameter (" time_jump_threshold" , 0.0 , descriptor);
68+ get_parameter (" time_jump_threshold" , time_jump_threshold);
69+ time_jump_threshold_duration_ =
70+ rclcpp::Duration::from_seconds (time_jump_threshold);
71+
6472 double yaw_offset = 0.0 ;
6573 declare_parameter (" yaw_offset" , 0.0 , descriptor);
6674 get_parameter (" yaw_offset" , yaw_offset);
@@ -128,6 +136,8 @@ ImuFilterMadgwickRos::ImuFilterMadgwickRos(const rclcpp::NodeOptions &options)
128136 " The gravity vector is kept in the IMU message." );
129137 }
130138
139+ last_ros_time_ = this ->get_clock ()->now ();
140+
131141 // **** define reconfigurable parameters.
132142 double gain;
133143 floating_point_range float_range = {0.0 , 1.0 , 0 };
@@ -151,7 +161,7 @@ ImuFilterMadgwickRos::ImuFilterMadgwickRos(const rclcpp::NodeOptions &options)
151161 add_parameter (" mag_bias_z" , rclcpp::ParameterValue (0.0 ), float_range,
152162 " Magnetometer bias (hard iron correction), z component." );
153163 double orientation_stddev;
154- float_range = {0.0 , 1 .0 , 0 };
164+ float_range = {0.0 , 100 .0 , 0 };
155165 add_parameter (" orientation_stddev" , rclcpp::ParameterValue (0.0 ),
156166 float_range,
157167 " Standard deviation of the orientation estimate." );
@@ -191,6 +201,10 @@ ImuFilterMadgwickRos::ImuFilterMadgwickRos(const rclcpp::NodeOptions &options)
191201 rpy_raw_debug_publisher_ =
192202 create_publisher<geometry_msgs::msg::Vector3Stamped>(" imu/rpy/raw" ,
193203 5 );
204+
205+ orientation_filtered_publisher_ =
206+ create_publisher<geometry_msgs::msg::PoseStamped>(
207+ " imu/orientation_filtered" , 5 );
194208 }
195209
196210 // **** register subscribers
@@ -220,6 +234,8 @@ ImuFilterMadgwickRos::ImuFilterMadgwickRos(const rclcpp::NodeOptions &options)
220234
221235void ImuFilterMadgwickRos::imuCallback (ImuMsg::ConstSharedPtr imu_msg_raw)
222236{
237+ checkTimeJump ();
238+
223239 std::lock_guard<std::mutex> lock (mutex_);
224240
225241 const geometry_msgs::msg::Vector3 &ang_vel = imu_msg_raw->angular_velocity ;
@@ -285,6 +301,8 @@ void ImuFilterMadgwickRos::imuCallback(ImuMsg::ConstSharedPtr imu_msg_raw)
285301void ImuFilterMadgwickRos::imuMagCallback (ImuMsg::ConstSharedPtr imu_msg_raw,
286302 MagMsg::ConstSharedPtr mag_msg)
287303{
304+ checkTimeJump ();
305+
288306 std::lock_guard<std::mutex> lock (mutex_);
289307
290308 const geometry_msgs::msg::Vector3 &ang_vel = imu_msg_raw->angular_velocity ;
@@ -480,9 +498,40 @@ void ImuFilterMadgwickRos::publishFilteredMsg(
480498
481499 rpy.header = imu_msg_raw->header ;
482500 rpy_filtered_debug_publisher_->publish (rpy);
501+
502+ publishOrientationFiltered (imu_msg);
483503 }
484504}
485505
506+ void ImuFilterMadgwickRos::publishOrientationFiltered (const ImuMsg &imu_msg)
507+ {
508+ geometry_msgs::msg::PoseStamped pose;
509+ pose.header .stamp = imu_msg.header .stamp ;
510+ pose.header .frame_id = fixed_frame_;
511+ pose.pose .orientation = imu_msg.orientation ;
512+
513+ // get the current transform from the fixed frame to the imu frame
514+ geometry_msgs::msg::TransformStamped transform;
515+ try
516+ {
517+ transform = tf_buffer_.lookupTransform (
518+ fixed_frame_, imu_msg.header .frame_id , imu_msg.header .stamp ,
519+ rclcpp::Duration::from_seconds (0.1 ));
520+ } catch (tf2::TransformException &ex)
521+ {
522+ RCLCPP_WARN (
523+ this ->get_logger (), " Could not get transform from %s to %s: %s" ,
524+ fixed_frame_.c_str (), imu_msg.header .frame_id .c_str (), ex.what ());
525+ return ;
526+ }
527+
528+ pose.pose .position .x = transform.transform .translation .x ;
529+ pose.pose .position .y = transform.transform .translation .y ;
530+ pose.pose .position .z = transform.transform .translation .z ;
531+
532+ orientation_filtered_publisher_->publish (pose);
533+ }
534+
486535void ImuFilterMadgwickRos::publishRawMsg (const rclcpp::Time &t, float roll,
487536 float pitch, float yaw)
488537{
@@ -545,6 +594,40 @@ void ImuFilterMadgwickRos::checkTopicsTimerCallback()
545594 << " ..." );
546595}
547596
597+ void ImuFilterMadgwickRos::checkTimeJump ()
598+ {
599+ const auto now = this ->get_clock ()->now ();
600+ if (last_ros_time_ == rclcpp::Time (0 , 0 , last_ros_time_.get_clock_type ()) ||
601+ last_ros_time_ <= now + time_jump_threshold_duration_)
602+ {
603+ last_ros_time_ = now;
604+ return ;
605+ }
606+
607+ RCLCPP_WARN (this ->get_logger (),
608+ " Detected jump back in time of %.1f s. Resetting IMU filter." ,
609+ (last_ros_time_ - now).seconds ());
610+
611+ if (time_jump_threshold_duration_ == rclcpp::Duration (0 , 0 ) &&
612+ this ->get_clock ()->get_clock_type () == RCL_SYSTEM_TIME)
613+ {
614+ RCLCPP_INFO (this ->get_logger (),
615+ " To ignore short time jumps back, use ~time_jump_threshold "
616+ " parameter of the filter." );
617+ }
618+
619+ reset ();
620+ }
621+
622+ void ImuFilterMadgwickRos::reset ()
623+ {
624+ std::lock_guard<std::mutex> lock (mutex_);
625+ filter_.reset ();
626+ initialized_ = false ;
627+ last_time_ = rclcpp::Time (0 , 0 , this ->get_clock ()->get_clock_type ());
628+ last_ros_time_ = this ->get_clock ()->now ();
629+ }
630+
548631#include " rclcpp_components/register_node_macro.hpp"
549632
550633RCLCPP_COMPONENTS_REGISTER_NODE (ImuFilterMadgwickRos)
0 commit comments