ROS话题发布和订阅节点的C++&Python实现

本文详细介绍了如何使用C++和Python在ROS(Robot Operating System)环境中创建话题发布者和订阅者,通过实例展示了如何编写代码并配置CMakeLists.txt,以及如何通过命令行测试和监控。

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

本文将分别使用C++和Python来实现话题发布者和订阅者,首先创建一个功能包,命名为topic_pub_sub,添加roscpprospy等依赖项。

C++实现

  • 创建话题发布者

在该功能包的src目录下创建publisher.cpp文件,添加如下程序:

#include <iostream>
#include <sstream>
#include <ros/ros.h> // 该文件包含了ROS系统中大部分常用的头文件
#include <std_msgs/String.h> // 消息类型的头文件,由.msg文件自动生成

int main(int argc, char** argv){
    // 初始化ROS
    ros::init(argc, argv, "publisher");
    // 为该节点创建一个句柄,创建后将会初始化这个节点
    ros::NodeHandle nh;
    // 创建一个类型为std_msgs::String的话题发布器,话题名为"msg",最后一个参数表示话题序列的大小
    ros::Publisher pub = nh.advertise<std_msgs::String>("msg", 1000);
    // 设置循环频率,单位: Hz
    ros::Rate loop_rate(10)
    int cnt = 0;
    while(ros::ok()){
        // 准备消息内容
        std_msgs::String msg;
        std::stringstream ss;
        ss << "hello world! " << cnt;
        msg.data = ss.str();
        
        // 打印发布的消息
        ROS_INFO("%s", msg.data.c_str());
        // 发布消息
        pub.publish(msg);
        // 消息回调处理,本程序不必调用该函数
        ros::spinOnce();
        // 休眠
        loop_rate.sleep();        
    }
}
  • 创建话题订阅者

src目录下创建subscriber.cpp文件,添加如下程序:

#include <iostream>
#include <ros/ros.h>
#include <std_msgs/String.h>

/**
 * @brief 回调函数
 * @param  msg              接收到的消息
 */
void callback(std_msgs::String::ConstPtr msg){
    ROS_INFO("%s", msg->data.c_str());
}

int main(int argc, char** argv){
    ros::init(argc, argv, "subscriber");
    ros::NodeHandle nh;

    // 订阅名为"msg"的话题,最后一个参数为回调函数,当接收到新消息时会调用这个函数
    ros::Subscriber sub = nh.subscribe("msg", 10, callback);
    // 回调处理函数
    ros::spin();
}
  • 修改CMakeList.txt

编辑该功能包的CMakeLists.txt文件,如下:

cmake_minimum_required(VERSION 3.0.2)
project(topic_pub_sub)

add_compile_options(-std=c++11)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

# 生成话题发布节点
add_executable(publisher src/publisher.cpp)
target_link_libraries(publisher
  ${catkin_LIBRARIES}
)
# 生成话题订阅节点
add_executable(subscriber src/subscriber.cpp)
target_link_libraries(subscriber
  ${catkin_LIBRARIES}
)

接下来使用catkin_make进行编译即可

  • 测试

需要运行三个终端,分别运行roscore,发布节点,订阅节点

  1. 运行roscore,在第一个终端输入:
roscore
  1. 运行话题发布者,在第二个终端中输入:
source ./devel/setup.bash
rosrun topic_pub_sub publisher
  1. 运行话题订阅者,在第三个终端中输入:
source ./devel/setup.bash
rosrun topic_pub_sub subscriber

结果如下:

01-发布者
02-订阅者
  • 使用ROS自带工具查看结果

使用rqt_graph命令可以查看节点间的关系,如图

03-graph

使用rostopic可以查看当前的话题状态、内容等数据,用法如下:

命令功能
rostopic list列举所有活动中的话题
rostopic echo <topic name>实时显示指定话题的消息内容
rostopic info <topic name>显示指定话题的信息

Python实现

相较于C++,Python实现会简单很多,也不需要编译,在一些简单的、对性能要求不高的场景,可以使用Python快速完成程序原型的设计

在开始前,要先在topic_pub_sub功能包目录下新建一个scripts文件夹

  • 创建话题发布者

scripts目录下创建publisher.py文件,内容如下:

#!/usr/bin/env python3
# #-*- coding: UTF-8 -*- 

import rospy
from std_msgs.msg import String

# 初始化ROS节点
rospy.init_node("publisher")
# 创建话题发布器,话题名称为"msg",类型为String
pub = rospy.Publisher("msg", String, queue_size=1000)
# 设置循环频率,单位: Hz
loop_rate = rospy.Rate(10)
cnt = 0
while not rospy.is_shutdown():
    msg = String()
    cnt += 1
    msg.data = "hello python! " + str(cnt)
    # 打印发布的消息
    rospy.loginfo(msg.data)
    # 发布消息
    pub.publish(msg)
    # 休眠
    loop_rate.sleep()

编写完成后,需要给这个文件执行权限,使用如下命令

sudo chmod 777 publisher.py
  • 创建话题订阅者

scripts目录下创建subscriber.py文件,内容如下:

#!/usr/bin/env python3
# #-*- coding: UTF-8 -*- 

import rospy
from std_msgs.msg import String

# 消息回调函数
def callback(msg):
    rospy.loginfo(msg.data)

# 初始化ROS节点
rospy.init_node("subscriber")
# 订阅名为"msg"的话题,最后一个参数为回调函数,当接收到新消息时会调用这个函数
sub = rospy.Subscriber("msg", String, callback)
# 回调处理
rospy.spin()

同样需要提高它的执行权限:

sudo chmod 777 subscriber.py
  • 测试

操作流程基本和C++实现一节基本一致,运行节点时可以直接使用rosrun topic_pub_sub xxxx.py来运行

### 如何通过 `roslaunch` 启动 ROS话题发布订阅节点ROS 中,`roslaunch` 是一种强大的工具,用于同时启动多个节点并管理复杂的依赖关系。要实现通过 `roslaunch` 启动一个话题发布订阅节点,可以按照以下方法设计配置文件。 #### 配置 launch 文件 创建一个新的 `.launch` 文件来定义需要启动的节点及其参数。假设我们有一个简单的发布者节点 (`talker_node`) 一个订阅者节点 (`listener_node`),它们分别负责发布接收 `/chatter` 主题的消息。 以下是示例 launch 文件的内容: ```xml <launch> <!-- 定义 talker 节点 --> <node pkg="my_package" type="talker_node" name="talker" output="screen"> <!-- 可选:设置参数 --> <param name="publish_rate" value="10"/> </node> <!-- 定义 listener 节点 --> <node pkg="my_package" type="listener_node" name="listener" output="screen"/> <!-- 如果有额外需求,比如条件化运行某些节点 --> <group if="$(arg condition)"> <node pkg="other_package" type="additional_node" name="extra_node"/> </group> </launch> ``` 上述代码中: - `<node>` 标签指定了包名 (`pkg`)、可执行文件名称 (`type`)、节点名称 (`name`) 以及日志输出方式 (`output`)。 - 参数可以通过 `<param>` 标签传递给节点[^1]。 - 使用 `<group>` 标签可以根据特定条件控制一组节点的行为[^3]。 #### 编写发布者订阅者PythonC++ 实现 为了使 `roslaunch` 正常工作,确保已编写好对应的发布者订阅者逻辑。这里提供了一个基于 Python 的简单例子作为参考。 ##### 发布者 (talker_node.py) ```python #!/usr/bin/env python import rospy from std_msgs.msg import String def talker(): pub = rospy.Publisher('chatter', String, queue_size=10) rospy.init_node('talker', anonymous=True) rate = rospy.Rate(10) # 设置发布频率为每秒 10 条消息 while not rospy.is_shutdown(): hello_str = "hello world %s" % rospy.get_time() rospy.loginfo(hello_str) pub.publish(String(data=hello_str)) rate.sleep() if __name__ == '__main__': try: talker() except rospy.ROSInterruptException: pass ``` ##### 订阅者 (listener_node.py) ```python #!/usr/bin/env python import rospy from std_msgs.msg import String def callback(msg): rospy.loginfo(rospy.get_caller_id() + ' I heard %s', msg.data) def listener(): rospy.init_node('listener', anonymous=True) rospy.Subscriber('chatter', String, callback) rospy.spin() if __name__ == '__main__': listener() ``` 以上两个脚本应保存至相应的 ROS 包目录下,并赋予可执行权限以便被 `roslaunch` 执行。 #### 运行 Launch 文件 完成上述配置后,在终端输入如下命令即可启动整个系统: ```bash roslaunch my_package example.launch ``` 其中 `example.launch` 即为我们之前编写的 launch 文件名字[^2]。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值