ROS 笔记(05)— 发布者 Publisher 和订阅者subscriber 的 Python 实现

这篇博客详细介绍了ROS(Robot Operating System)中的话题通信机制,包括发布订阅模式、服务通信和参数服务器。通过一个实例展示了如何创建ROS节点、发布者和订阅者,以及如何在小海龟仿真环境中实现数据交换。读者可以了解到ROS中如何通过话题通信来传递传感器数据,如激光雷达信息,并通过编写Python脚本来控制机器人运动。

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

机器人是一种高度复杂的系统性实现,在机器人上可能集成各种传感器(雷达、摄像头、GPS…)以及运动控制实现,为了解耦合,在 ROS 中每一个功能点都是一个单独的进程,每一个进程都是独立运行的。

更确切的讲,ROS 是进程(也称为Nodes)的分布式框架。 因为这些进程甚至还可分布于不同主机,不同主机协同工作,从而分散计算压力。不过随之也有一个问题: 不同的进程是如何通信的?也即不同进程间如何实现数据交换的?在此我们就需要介绍一下 ROS 中的通信机制了。

ROS 中的基本通信机制主要有如下三种实现策略:

  • 话题通信(发布订阅模式)
  • 服务通信(请求响应模式)
  • 参数服务器(参数共享模式)

话题通信是 ROS 中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。话题通信的应用场景也极其广泛,比如下面一个常见场景:

机器人在执行导航功能,使用的传感器是激光雷达,机器人会采集激光雷达感知到的信息并计算,然后生成运动控制信息驱动机器人底盘运动。

在上述场景中,就不止一次使用到了话题通信。

  • 以激光雷达信息的采集处理为例,在 ROS 中有一个节点需要时时的发布当前雷达采集到的数据,导航模块中也有节点会订阅并解析雷达数据。
  • 再以运动消息的发布为例,导航模块会根据传感器采集的数据时时的计算出运动控制信息并发布给底盘,底盘也可以有一个节点订阅运动信息并最终转换成控制电机的脉冲信号。

以此类推,像雷达、摄像头、GPS… 等等一些传感器数据的采集,也都是使用了话题通信,换言之,话题通信适用于不断更新的数据传输相关的应用场景。

1. 发布者 Publisher

1.1 话题模型

首先我们要实现下图所示的话题模型,该模型如下图所示,该模型中涉及到三个角色:

  • ROS Master (管理者)
  • Talker (发布者)
  • Listener (订阅者)

ROS Master 负责保管 TalkerListener 注册的信息,并匹配话题相同的 TalkerListener,帮助 TalkerListener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅。

huati其中,主题名称节点为 /turtle1/cmd_vel ,发布者和订阅者的消息类型为 geometry_msgs::Twist

1.2 创建功能包

src 目录下创建功能包,包名为 topic_demo,依赖分别为 rospystd_msgsgeometry_msgs

wohu@wohu-pc:~/project/ros/ros_demo/src$ catkin_create_pkg  topic_demo rospy std_msgs geometry_msgs 

输出如下:

turtlesim Created file topic_demo/package.xml
Created file topic_demo/CMakeLists.txt
Created folder topic_demo/src
Successfully created files in /home/wohu/project/ros/ros_demo/src/topic_demo. Please adjust the values in package.xml.

1.3 创建发布者代码

在功能包下面建立一个 scripts 文件夹,在 scripts 文件里面建立一个 .py 文件。

pbu
publisher.py 代码内容:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist

import rospy
from geometry_msgs.msg import Twist

def velocity_publisher():
	# ROS节点初始化
    rospy.init_node('velocity_publisher', anonymous=True)

	# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
    turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)

	#设置循环的频率
    rate = rospy.Rate(10) 

    while not rospy.is_shutdown():
		# 初始化geometry_msgs::Twist类型的消息
        vel_msg = Twist()
        vel_msg.linear.x = 0.5
        vel_msg.angular.z = 0.2

		# 发布消息
        turtle_vel_pub.publish(vel_msg)
    	rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
				vel_msg.linear.x, vel_msg.angular.z)

		# 按照循环频率延时
        rate.sleep()

if __name__ == '__main__':
    try:
        velocity_publisher()
    except rospy.ROSInterruptException:
        pass

1.4 修改 Python 代码可执行权限

$ chmod +x publisher.py 

1.5 运行发布者代码

  • 执行 roscore 启动 ROS 服务
$ roscore
  • 启动小海龟仿真器
    我们再打开一个终端,执行如下命令
$ rosrun turtlesim turtlesim_node 
  • 运行发布者代码
$ rosrun topic_demo publisher.py

rosrun 后面跟着创建的包名 topic_demo 和发布者的文件 publisher.py

演示结果如下:
demo
如果运行后报错:

$ rosrun topic_demo publisher.py 
[rosrun] Couldn't find executable named publisher.py below /home/wohu/project/ros/ros_demo/src/topic_demo
[rosrun] Found the following, but they're either not files,
[rosrun] or not executable:
[rosrun]   /home/wohu/project/ros/ros_demo/src/topic_demo/scripts/publisher.py
wohu@wohu-pc:~/project/ros/ros_demo/src$

说明 publisher.py 文件权限没有修改。

2. 订阅者subscriber

dingyue和前面一样,在功能包 topic_demo 目录的 src 目录下存放订阅者文件

cc
订阅者代码实现

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose

import rospy
from turtlesim.msg import Pose

def poseCallback(msg):
    rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)

def pose_subscriber():
	# ROS节点初始化
    rospy.init_node('pose_subscriber', anonymous=True)

	# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    rospy.Subscriber("/turtle1/pose", Pose, poseCallback)

	# 循环等待回调函数
    rospy.spin()

if __name__ == '__main__':
    pose_subscriber()

依次分别打开 3 个终端执行下面命令:

$ roscore 
$ rosrun turtlesim turtlesim_node 
$ rosrun turtlesim turtle_teleop_key

通过下面命令启动订阅者

$ rosrun topic_demo pose_subscriber.py

通过上、下、左、右 控制海龟移动,然后就可以看到 pose_subscriber.py 脚本输出海龟的位置信息了。

3. 其它

经过测试验证,publisher.py 代码也可以放在 src 目录下

ds
更改脚本名称后运行下面命令,也是可以运行起来的。

$ rosrun topic_demo publisher_demo.py
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wohu007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值