【ROS入门篇·三】ROS通讯架构-Topic

本文介绍了ROS中的Topic通讯机制,包括Publisher和Subscriber的概念及使用。通过C++示例展示了如何创建发布节点和订阅节点,以及自定义消息的生成。此外,还提供了一个在同一节点内同时订阅和发布Topic的示例。

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

快速链接:【ROS入门篇】ROS学习简介

一、ROS中Topic通讯机制

Topic: 异步通讯机制,topic可以同时有多个subscribers,也可以有多个publishers;

Publisher: 向指定话题,发布对应类型的消息;

Sublisher: 订阅话题,一旦话题消息存在,调用回调函数对消息进行处理。

二、Publisher节点示例

  • C++实现(古月居案例)
/**
    * pub_demo.cpp, 发布turtle/cmd_vel话题,消息类型为geometry_msgs::Twist
    */

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "pub_demo_node");

    // 创建ROS节点句柄
    ros::NodeHandle n_;

    // 创建一个Publisher,发布turtle/cmd_vel话题,消息类型为geometry_msgs::Twist,队列长度为10
    ros::Publisher pub_ = n_.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);

    // 设置循环频率
    ros::Rate loop_rate(10);

    int count=0;
    while(ros::ok())
    {
        // 初始化类型为geometry_msgs::Twist的消息
        geometry_msgs::Twist vel_msg;
        vel_msg.linear.x=0.5;
        vel_msg.linear.z=0.2;

        // 发布消息
        pub_.publish(vel_msg);
        ROS_INFO("Publish turtle velocity command[%0.2f m/s, %0.2f rad/s]", vel_msg.linear.x, vel_msg.linear.z);

        // 按照循环频率执行
        loop_rate.sleep();
    }

    return 0;
}
  • 修改CMakeLists.txt,配置可执行.cpp文件信息

三、Subscriber节点示例

  • C++实现(古月居案例)
/**
 * sub_demo.cpp, 订阅/turtle1/pose话题,消息类型为turtlesim::Pose
 */

#include <ros/ros.h>
#include <turtlesim/Pose.h>

void Callback(const turtlesim::Pose::ConstPtr& msg)
{
    ROS_INFO("Turtle pose  x: %0.6f,  y: %0.6f", msg->x, msg->y);
}

int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "sub_demo_node");

    // 创建ROS节点句柄
    ros::NodeHandle n_;

    // 创建一个Subscriber,订阅/turtle1/pose话题,消息类型为turtlesim::Pose,队列长度为10,注册回调函数Callback()
    ros::Subscriber sub_ = n_.subscribe("/turtle1/Pose", 10, Callback);

    // 主程序阻塞在这里,循环等待回调函数
    ros::spin();
}
  • 修改CMakeLists.txt,配置可执行.cpp文件信息

四、自定义消息

  • 生成.msg文件,放在msg文件夹内
  • 修改CMakeLists.txt和Package.xml文件
/* .msg文件示例,定义了一个表示people的消息类型  */

string name
uint8 sex
uint8 age

uint8 unknow=0
uint8 male=1
uint8 female=2

五、PubAndSub节点示例

  • 同一节点内订阅一个话题,并发布一个话题
/**
    * SubAndPub_demo.cpp
    * 订阅/velodyne_points话题,消息类型为sensor_msgs::PointCloud2
    * 发布/processed_velodyne_points话题,消息类型为sensor_msgs::PointCloud2
    */

#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/point_cloud.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl_ros/point_cloud.h>

using namespace std; 

class SubAndPub
{
private:
  ros::NodeHandle n_; 
  ros::Publisher pub_;
  ros::Subscriber sub_;
  std::string frame_id_;
 
public:
  SubAndPub();
  void callback(const sensor_msgs::PointCloud2& velodyne_sub);
  void pub_cloud(ros::Publisher pub_, const pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_out);
};// End of class SubscribeAndPublish
 
SubAndPub::SubAndPub()
{
  // Topic you want to publish
  pub_ = n_.advertise<sensor_msgs::PointCloud2>("/processed_velodyne_points",1);

  // Topic you want to subscribe
  sub_ = n_.subscribe("/velodyne_points", 1, &SubAndPub::callback,this);
}

void SubAndPub::callback(const sensor_msgs::PointCloud2& cloud_in)
{
  // do something with the input and generate the output...
  frame_id_ = cloud_in.header.frame_id;
  pcl::PointCloud<pcl::PointXYZI>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZI>);
  pcl::fromROSMsg(cloud_in,*cloud);
  pub_cloud(pub_,cloud);
}

void SubAndPub::pub_cloud(ros::Publisher pub_, const pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_out)
{
    sensor_msgs::PointCloud2 out;
    pcl::toROSMsg(*cloud_out,out);
    out.header.frame_id = frame_id_;
    pub_.publish(out);
}

int main(int argc, char **argv)
{
  // Initiate ROS
  ros::init(argc, argv, "SubAndPub_demo_node");
 
  // Create an object of class SubscribeAndPublish that will take care of everything
  SubAndPub velodyne;
 
  ros::spin();
  return 0;
}
  • 修改CMakeLists.txt和package.xml,配置可执行.cpp文件信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值