关于ROS在一个回调函数中处理两个订阅话题消息(多话题回调、多参数回调问题)

文章介绍了如何在一个ROS节点中处理来自多个主题的回调函数,涉及boost::bind和message_filters库的使用,以及解决多话题同步回调的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近遇到需要在一个回调函数中处理多话题消息的问题,特此记录下在一个回调函数中处理多话题、多参数的方法。

举例:

#include <iostream>
#include <boost/bind.hpp>

#include <ros/ros.h>

#include <sensor_msgs/Image.h>
#include "detectmsg/SpatialDetection.h"
#include "detectmsg/SpatialDetectionArray.h"
#include "detectmsg/pose2D.h"
#include "detectmsg/multi_pedestrian_pose.h"
 
ros::Publisher obj_pub_;
ros::Subscriber  obj_sub_;
ros::Subscriber  image_sub_;

int Class_ID;

std::string pub_topic;
std::string sub_topic;

void Callback(const detectmsg::SpatialDetectionArray::ConstPtr& detect, const sensor_msgs::Image::ConstPtr& image)
{
  ROS_INFO("ok!");
}
 
int main(int argc, char **argv)
{
    ros::init(argc, argv, "obj_publish_node");
    ros::NodeHandle nh;

    int ErrorParam=0;

    ErrorParam += !nh.getParam("objdetectnode/Class_ID_", Class_ID);

    ErrorParam += !nh.getParam("objdetectnode/pub_topic_", pub_topic);
    ErrorParam += !nh.getParam("objdetectnode/sub_topic_", sub_topic);


    if(ErrorParam>0){
      ROS_INFO("Error Param Load! Error Number:%d",ErrorParam);
      return 1;
    }

    ROS_INFO("SUCCESSFULLY STARTED");

    obj_pub_ = nh.advertise<detectmsg::multi_pedestrian_pose>(pub_topic, 1);
    obj_sub_ = nh.subscribe<detectmsg::SpatialDetectionArray>(sub_topic, 1, boost::bind(&Callback, _1 , sensor_msgs::Image::ConstPtr()));
    image_sub_ = nh.subscribe<sensor_msgs::Image>("/yolov4_publisher/color/image", 1, boost::bind(&Callback, detectmsg::SpatialDetectionArray::ConstPtr(), _1));
   
    ros::spin();
    return 0;
}

这是一段没写完的代码,主要用来测试一下多参数回调问题,最关键的部分在订阅话题的两端代码上,其他的代码不用看,需要注意到地方会在下文提到。

1、要实现多话题回调需要包含头文件,对应代码:#include <boost/bind.hpp>

2、要实现两个话题传向一个回调函数,首先先分别写出两个订阅话题的代码,最常用的订阅话题的代码段格式为:

obj_sub_ = nh.subscribe<detectmsg::SpatialDetectionArray>(sub_topic, 1, &Callback);

要实现多话题回调需要使用到函数boost::bind(),这里可以参考上文的代码(以obj_sub_为例),将原来回调函数的位置替换为该函数,函数内有三个参数,第一个是这两个话题进行绑定后共同传入的回调函数名称,第二个参数是一个占位符,为下面的话题订阅占位,最后一位为传入当前语句订阅的话题,注意结尾的::ConstPtr()。

image_sub_的语句是类似的,唯一的区别是占位的时候需要注意占位符位置的变化以及消息格式已经变成了上一个话题的消息格式。这里我特意选择了两个不同的消息格式防止混淆,相信各位一对比就能很清楚的明白其中的规律。

最后就是注意下一下在回调函数的参数部分,两个参数的顺序不能颠倒,同时注意const。

---------------------------------------------------------------------------------------------------------------------------------

上面代码经过测试是正常运行的,但是我尝试进行三个话题的同步回调时遇到了问题,按照上述写法,在回调函数中每次只能读取到一个话题的消息,不知道是因为时间同步问题导致还是代码里逻辑有问题,总之运行是不正确的,运行有问题的代码如下:

    // obj_sub_ = nh.subscribe<yolov5_ros_msgs::BoundingBoxes>("/yolov5/BoundingBoxes", 1, 
    //     boost::bind(&Callback, _1 , sensor_msgs::Image::ConstPtr(),sensor_msgs::CameraInfo::ConstPtr()));
    // image_sub_ = nh.subscribe<sensor_msgs::Image>("/stereo_publisher/stereo/depth", 1, 
    //     boost::bind(&Callback, yolov5_ros_msgs::BoundingBoxes::ConstPtr(), _1,sensor_msgs::CameraInfo::ConstPtr()));
    // caminfo_sub_ = nh.subscribe<sensor_msgs::CameraInfo>("/stereo_publisher/stereo/camera_info", 1, 
    //     boost::bind(&Callback, yolov5_ros_msgs::BoundingBoxes::ConstPtr(), sensor_msgs::Image::ConstPtr(),_1));

这段代码语法上是没有问题的,是可以编译通过的,我因为该代码的不正确运行,报的段错误,找到错误花了些时间,有一定迷惑性。

找到错误后更换了订阅话题方法,新方法用到了message_filters这个库,没有安装的话用下面的代码安装即可:

 sudo apt-get install ros-melodic-message-filters
//中间部分换成自己的版本

使用时包含头文件并并在cmakelists文件中find package部分进行添加

//头文件
#include<message_filters/subscriber.h>
#include<message_filters/time_synchronizer.h>

----------------------------------------------------
//CMakelists.txt

find_package(catkin REQUIRED COMPONENTS
  ...
  message_filters
)

...

target_link_libraries(your_executable_name
  ...
  ${catkin_LIBRARIES}
)

cpp中使用方法,还是上面的例子:

    message_filters::Subscriber<yolov5_ros_msgs::BoundingBoxes> detect_sub(nh, "/yolov5/BoundingBoxes", 1);
    message_filters::Subscriber<sensor_msgs::Image> image_sub(nh, "/stereo_publisher/stereo/depth", 1);
    message_filters::Subscriber<sensor_msgs::CameraInfo> caminfo_sub(nh, "/stereo_publisher/stereo/camera_info", 1);

    message_filters::TimeSynchronizer<yolov5_ros_msgs::BoundingBoxes, sensor_msgs::Image, sensor_msgs::CameraInfo> sync(detect_sub, image_sub, caminfo_sub, 10);
    sync.registerCallback(boost::bind(&Callback, _1, _2, _3));
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值