ROS2教程 08 话题通信Topic

零、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="[email protected]">Herman Yemaintainer>
<license>Apache License 2.0license>

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

<exec_depend>rclpyexec_depend>
<exec_depend>std_msgsexec_depend>

5.添加入口点

打开setup.py,添加入口点

maintainer='Herman Ye',
maintainer_email='[email protected]',
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

你可能感兴趣的:(ROS2,自动驾驶,python,人工智能)