ROS2教程 08 话题通信Topic

发布时间:2024-01-02 15:00

零、Topic机制

在ROS2中已经没有了Master的概念,避免master挂了,以提升系统的稳定性

一、发布者Publisher

1.新建功能包

ros2 pkg create --build-type ament_python py_pub_sub

2.新建源码文件

在py_pub_sub功能包的py_pub_sub文件夹下新建源码文件publisher_member_function.py

touch publisher_member_function.py

3.编写源码

ros2中提供的消息接口可以通过以下命令来查看

ros2 interface list

进而查看具体的消息类型的结构

ros2 interface show std_msgs/msg/String
OUTPUT:
# This was originally provided as an example message.
# It is deprecated as of Foxy
# It is recommended to create your own semantically meaningful message.
# However if you would like to continue using this please use the equivalent in example_msgs.

string data

以下为源码:

import rclpy # rclpy是ROS Client Library for Python的缩写,与Node有关的内容在这个库中
from rclpy.node import Node 
from std_msgs.msg import String # std_msgs是ROS内置的数据类型库,里面有msg、srv等一系列基础的数据类型 


class MinimalPublisher(Node): # Node为这个类的父类

    def __init__(self):
        super().__init__(\'minimal_publisher\') # 调用父类中Node的构造函数,在此处直接为其赋名minimal_publisher
        # 创建publisher,数据类型为String,话题名为topic_name, 队列长度为10,它是QoS (quality of service) setting之一
        self.example_publisher = self.create_publisher(String, \'topic_name\', 10)        
        timer_period = 0.5  # 定时器周期 in seconds
        self.timer = self.create_timer(timer_period, self.timer_callback) # 创建定时器 每个周期调用一次回调函数self.timer_callback
        self.i = 0 # 用于回调函数的一个计数器counter

    def timer_callback(self): # 定时器的回调函数
        msg = String() # 定义消息类型为String类
        msg.data = \'Hello World: %d\' % self.i # 添加消息内容
        self.example_publisher.publish(msg) # 发布消息
        self.get_logger().info(\'Publishing: \"%s\"\' % msg.data) # 可选的打印日志到控制台console
        self.i += 1

# 上面的部分为类内容
# 下面的部分是main函数
def main(args=None):
    rclpy.init(args=args) # 初始化 rclpy

    minimal_publisher = MinimalPublisher() # 定义MinimalPublisher类

    rclpy.spin(minimal_publisher) # 循环

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    minimal_publisher.destroy_node() # 可以不写,会自动之心
    rclpy.shutdown() #关闭


if __name__ == \'__main__\': # 该条下的所有代码仅当本脚本直接执行时会触发,如果在其他文件引用本文件,则不会触发以下的代码
    main()

4.添加依赖

在功能包目录下打开package.xml,修改以下内容[可选,不影响使用]
例子:

<description>Examples of minimal publisher/subscriber using rclpydescription>
<maintainer email=\"hermanye233@icloud.com\">Herman Yemaintainer>
<license>Apache License 2.0license>

继续添加内容[必须]
当功能包里的代码被执行时,这些语句声明了功能包的依赖

<exec_depend>rclpyexec_depend>
<exec_depend>std_msgsexec_depend>

5.添加入口点

打开setup.py,添加入口点

maintainer=\'Herman Ye\',
maintainer_email=\'hermanye233@icloud.com\',
description=\'Examples of minimal publisher/subscriber using rclpy\',
license=\'Apache License 2.0\',

在entry_points下的这个位置添加以下命令

\'talker = py_pub_sub.publisher_member_function:main\',

最终效果:

entry_points={
    \'console_scripts\': [
    \'talker = py_pub_sub.publisher_member_function:main\',
    ],
},

6.检查setup.cfg

setup.cfg是自动填写的,它将功能包的可执行文件放入lib中,ros2 run将会在lib中查找这些执行性文件是否存在并调用

[develop]
script_dir=$base/lib/py_pub_sub
[install]
install_scripts=$base/lib/py_pub_sub

二、订阅 subscription

1.新建源码文件

在功能包src文件夹下新建源码文件pose_subscriber.cpp

touch pose_subscriber.cpp

2.编写源码

源码部分注释同publisher

import rclpy 
from rclpy.node import Node

from std_msgs.msg import String 


class MinimalSubscriber(Node):

    def __init__(self):
        super().__init__(\'minimal_subscriber\')
        # 订阅者的构造函数和回调函数不需要定时器Timer,因为当收到Message时,就已经启动回调函数了
        # 注意此处不是subscriber,而是subscription
        # 数据类型,话题名,回调函数名,队列长度
        self.subscription = self.create_subscription(String,\'topic_name\',self.listener_callback,10)
        self.subscription  # prevent unused variable warning

    def listener_callback(self, msg):
        self.get_logger().info(\'I heard: \"%s\"\' % msg.data) #回调函数内容为打印msg.data里的内容


def main(args=None):
    rclpy.init(args=args)

    minimal_subscriber = MinimalSubscriber()

    rclpy.spin(minimal_subscriber)

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    minimal_subscriber.destroy_node()
    rclpy.shutdown()


if __name__ == \'__main__\':
    main()

3.添加依赖

因为之前添加过了,所以不用再添加,如果subscriber有额外要使用的库,则需要添加新增的库

5.添加入口点

打开setup.py,添加入口点
在entry_points下的这个位置添加以下命令

\'listener = py_pub_sub.subscriber_member_function:main\',

最终效果:

    entry_points={
        \'console_scripts\': [
        \'talker = py_pub_sub.publisher_member_function:main\',
        \'listener = py_pub_sub.subscriber_member_function:main\',
        ],
    },

ros2 run 在功能包中所能观测到的可执行文件的名字即此处设置的talker与listener

三、测试发布-话题-订阅通信

1.编译

colcon build --packages-select py_pub_sub

2.运行测试

ros2 run py_pub_sub listener
ros2 run py_pub_sub talker

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号