You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS2 Humble类内注册message_filters非静态同步回调问题

ROS2 Humble中message_filters同步器注册非静态类成员回调的解决方案

问题描述

在ROS2 Humble中使用message_filters的Synchronizer结合Approximate Time Policy实现消息同步时,类外注册回调功能正常,但类内注册非静态成员函数作为回调时编译报错,提示无法匹配回调函数类型。

现有代码

回调函数

void performNDT(const sensor_msgs::msg::LaserScan &lidar_msg, const nav_msgs::msg::Odometry &odom_msg)
{
  std::cout << "Hello sync world" << std::endl;
}

同步策略与同步器定义

typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::msg::LaserScan, nav_msgs::msg::Odometry> approximate_time_sync_policy;
message_filters::Synchronizer<approximate_time_sync_policy> synchronizer;

类构造函数

LandmarkExtractor()
: Node("landmark_extractor"),
synchronizer(approximate_time_sync_policy(10), lidar_sub, odom_sub)
{      
  /******* QOS SETTINGS *******/
  custom_qos_profile.depth = 1;
  custom_qos_profile.reliability = rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT;
  custom_qos_profile.history = rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_LAST;
  custom_qos_profile.durability = rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT;

  // Subscribing to Odometry and LaserScan msg topics
  lidar_sub.subscribe(this, "scan", custom_qos_profile);
  odom_sub.subscribe(this, "odom", custom_qos_profile);

  // Registering synced callback
  synchronizer.registerCallback(std::bind(&LandmarkExtractor::performNDT,this, _1, _2));

...
}

订阅器定义

// Subscribers
message_filters::Subscriber<sensor_msgs::msg::LaserScan> lidar_sub;
message_filters::Subscriber<nav_msgs::msg::Odometry> odom_sub;

编译错误

error: no matching function for call to ‘message_filters::Signal9<std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > >, std::shared_ptr<nav_msgs::msg::Odometry_<std::allocator<void> > >, message_filters::NullType, message_filters::NullType, message_filters::NullType, message_filters::NullType, message_filters::NullType, message_filters::NullType, message_filters::NullType>::addCallback<const M0ConstPtr&, const M1ConstPtr&, const M2ConstPtr&, const M3ConstPtr&, const M4ConstPtr&, const M5ConstPtr&, const M6ConstPtr&, const M7ConstPtr&, const M8ConstPtr&>(std::_Bind_helper<false, const std::_Bind<void (LandmarkExtractor::*(LandmarkExtractor*, std::_Placeholder<1>, std::_Placeholder<2>))(const std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > >&, const std::shared_ptr<nav_msgs::msg::Odometry_<std::allocator<void> > >&)>&, const std::_Placeholder<1>&, const std::_Placeholder<2>&, const std::_Placeholder<3>&, const std::_Placeholder<4>&, const std::_Placeholder<5>&, const std::_Placeholder<6>&, const std::_Placeholder<7>&, const std::_Placeholder<8>&, const std::_Placeholder<9>&>::type)’
  272 |     return addCallback<const M0ConstPtr&,
      |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  273 |                      const M1ConstPtr&,
      |                      ~~~~~~~~~~~~~~~~~~ 
  274 |                      const M2ConstPtr&,
      |                      ~~~~~~~~~~~~~~~~~~ 
  275 |                      const M3ConstPtr&,
      |                      ~~~~~~~~~~~~~~~~~~ 
  276 |                      const M4ConstPtr&,
      |                      ~~~~~~~~~~~~~~~~~~ 
  277 |                      const M5ConstPtr&,
      |                      ~~~~~~~~~~~~~~~~~~ 
  278 |                      const M6ConstPtr&,
      |                      ~~~~~~~~~~~~~~~~~~ 
  279 |                      const M7ConstPtr&,
      |                      ~~~~~~~~~~~~~~~~~~ 
  280 |                      const M8ConstPtr&>(std::bind(callback, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6, std::placeholders::_7, std::placeholders::_8, std::placeholders::_9));
      |                      ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/ros/humble/include/message_filters/message_filters/synchronizer.h:47,
                 from /opt/ros/humble/include/message_filters/message_filters/time_synchronizer.h:41,
                 from /home/jan/ros_ws/src/shamanbot/src/landmark_extraction.cpp:8:
/opt/ros/humble/include/message_filters/message_filters/signal9.h:170:14: note: candidate: ‘message_filters::Connection message_filters::Signal9<M0, M1, M2, M3, M4, M5, M6, M7, M8>::addCallback(const std::function<void(P0, P1, P2, P3, P4, P5, P6, P7, P8)>&) [with P0 = const std::shared_ptr<const std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > > >&; P1 = const std::shared_ptr<const std::shared_ptr<nav_msgs::msg::Odometry_<std::allocator<void> > > >&; P2 = const std::shared_ptr<const message_filters::NullType>&; P3 = const std::shared_ptr<const message_filters::NullType>&; P4 = const std::shared_ptr<const message_filters::NullType>&; P5 = const std::shared_ptr<const message_filters::NullType>&; P6 = const std::shared_ptr<const message_filters::NullType>&; P7 = const std::shared_ptr<const message_filters::NullType>&; P8 = const std::shared_ptr<const message_filters::NullType>&; M0 = std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > >; M1 = std::shared_ptr<nav_msgs::msg::Odometry_<std::allocator<void> > >; M2 = message_filters::NullType; M3 = message_filters::NullType; M4 = message_filters::NullType; M5 = message_filters::NullType; M6 = message_filters::NullType; M7 = message_filters::NullType; M8 = message_filters::NullType]’
  170 |   Connection addCallback(const std::function<void(P0, P1, P2, P3, P4, P5, P6, P7, P8)>& callback)
      |              ^~~~~~~~~~~
/opt/ros/humble/include/message_filters/message_filters/signal9.h:170:89: note:   no known conversion for argument 1 from ‘std::_Bind_helper<false, const std::_Bind<void (LandmarkExtractor::*(LandmarkExtractor*, std::_Placeholder<1>, std::_Placeholder<2>))(const std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > >&, const std::shared_ptr<nav_msgs::msg::Odometry_<std::allocator<void> > >&)>&, const std::_Placeholder<1>&, const std::_Placeholder<2>&, const std::_Placeholder<3>&, const std::_Placeholder<4>&, const std::_Placeholder<5>&, const std::_Placeholder<6>&, const std::_Placeholder<7>&, const std::_Placeholder<8>&, const std::_Placeholder<9>&>::type’ to ‘const std::function<void(const std::shared_ptr<const std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > > >&, const std::shared_ptr<const std::shared_ptr<nav_msgs::msg::Odometry_<std::allocator<void> > > >&, const std::shared_ptr<const message_filters::NullType>&, const std::shared_ptr<const message_filters::NullType>&, const std::shared_ptr<const message_filters::NullType>&, const std::shared_ptr<const message_filters::NullType>&, const std::shared_ptr<const message_filters::NullType>&, const std::shared_ptr<const message_filters::NullType>&, const std::shared_ptr<const message_filters::NullType>&)>&’
  170 |   Connection addCallback(const std::function<void(P0, P1, P2, P3, P4, P5, P6, P7, P8)>& callback)
      |                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
/opt/ros/humble/include/message_filters/message_filters/signal9.h:180:14: note: candidate: ‘template<class P0, class P1> message_filters::Connection message_filters::Signal9<M0, M1, M2, M3, M4, M5, M6, M7, M8>::addCallback(void (*)(P0, P1)) [with P0 = P0; P1 = P1; M0 = std::shared_ptr<sensor_msgs::msg::LaserScan_<std::allocator<void> > >; M1 = std::shared_ptr<nav_msgs::msg::Odometry_<std::allocator<void> > >; M2 = message_filters::NullType; M3 = message_filters::NullType; M4 = message_filters::NullType; M5 = message_filters::NullType; M6 = message_filters::NullType; M7 = message_filters::NullType; M8 = message_filters::NullType]’
  180 |   Connection addCallback(void(*callback)(P0, P1))

解决方法

1. 修正回调函数参数类型

message_filters的同步回调默认传递std::shared_ptr<const MsgType>类型,而非原始消息引用,需调整回调参数类型:

void performNDT(const std::shared_ptr<const sensor_msgs::msg::LaserScan>& lidar_msg, 
                const std::shared_ptr<const nav_msgs::msg::Odometry>& odom_msg)
{
  std::cout << "Hello sync world" << std::endl;
  // 访问消息内容使用->操作符,例如 lidar_msg->header.stamp
}

2. 正确注册回调(两种方式)

方式一:Lambda表达式(推荐)

Lambda可直接捕获this指针,语法直观,避免std::bind的类型匹配问题:

// 替换构造函数中原registerCallback代码
synchronizer.registerCallback(
  [this](const std::shared_ptr<const sensor_msgs::msg::LaserScan>& lidar_msg, 
         const std::shared_ptr<const nav_msgs::msg::Odometry>& odom_msg) {
    this->performNDT(lidar_msg, odom_msg);
  }
);

方式二:std::bind

若坚持使用std::bind,需确保绑定函数参数与回调期望类型完全匹配:

synchronizer.registerCallback(
  std::bind(&LandmarkExtractor::performNDT, this, 
            std::placeholders::_1, std::placeholders::_2)
);

3. 调整同步器初始化顺序(可选)

原代码在初始化列表创建同步器时,订阅器尚未完成订阅,存在潜在风险。可将同步器改为智能指针,在构造函数中完成订阅后再初始化:

// 类内同步器定义修改为
std::unique_ptr<message_filters::Synchronizer<approximate_time_sync_policy>> synchronizer;

// 构造函数内调整逻辑
LandmarkExtractor() : Node("landmark_extractor")
{      
  // ... QOS配置代码 ...

  // 先完成订阅
  lidar_sub.subscribe(this, "scan", custom_qos_profile);
  odom_sub.subscribe(this, "odom", custom_qos_profile);

  // 再初始化同步器
  synchronizer = std::make_unique<message_filters::Synchronizer<approximate_time_sync_policy>>(
    approximate_time_sync_policy(10), lidar_sub, odom_sub
  );

  // 注册回调
  synchronizer->registerCallback(/* 上述Lambda或bind代码 */);
}

验证编译

修改完成后执行colcon build即可正常编译,运行节点后同步回调会被正确触发。

内容的提问来源于stack exchange,提问作者JanSam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:12:00