编写监听器(Python)

目标 了解如何使用 tf2 获取帧变换。

辅导水平: 中级

时间 10 分钟

背景介绍

在之前的教程中,我们创建了一个 tf2 广播器,用于向 tf2 发布乌龟的姿势。

在本教程中,我们将创建一个 tf2 监听器,开始使用 tf2。

先决条件

本教程假定您已经完成了 tf2 静态广播器教程(Python)tf2 广播员教程(Python).在上一教程中,我们创建了一个 学习_tf2_py 这也是我们将继续开展工作的基础。

任务

1 写入监听节点

首先创建源文件。转到 学习_tf2_py 软件包。在 src/learning_tf2_py/learning_tf2_py 输入以下命令,下载监听器示例代码:

wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.py

现在打开名为 turtle_tf2_listener.py 使用您喜欢的文本编辑器。

舶来品 算术

 几何_msgs.msg 舶来品 扭转

舶来品 rclpy
 rclpy.node 舶来品 节点

 tf2_ros 舶来品 转换异常
 tf2_ros.buffer 舶来品 缓冲器
 tf2_ros.transform_listener 舶来品 变换监听器

 turtlesim.srv 舶来品 再生


 帧监听器(节点):

    捍卫 启动(自我):
        棒极了().启动('turtle_tf2_frame_listener';)

        # 声明并获取 `target_frame` 参数
        自我.target_frame = 自我.declare_parameter(
          'target_frame', 'turtle1';).获取参数值().string_value

        自我.tf_buffer = 缓冲器()
        自我.tf_listener = 变换监听器(自我.tf_buffer, 自我)

        # 创建一个客户端来生成乌龟
        自我.产卵器 = 自我.创建客户端(再生, '产卵';)
        # 用布尔值存储信息
        # 如果可以提供产卵龟服务
        自我.乌龟产卵服务准备就绪 = 假的
        # 如果乌龟成功产卵
        自我.乌龟产卵 = 假的

        # 创建海龟 2 速度发布器
        自我.出版商 = 自我.创建出版商(扭转, 'turtle2/cmd_vel', 1)

        # 每秒调用一次 on_timer 函数
        自我.定时器 = 自我.创建计时器(1.0, 自我.on_timer)

    捍卫 on_timer(自我):
        # 在变量中存储帧名,这些变量将用于
        # 计算变换
        从帧关系 = 自我.target_frame
        至框架关系 = 'turtle2';

        如果 自我.乌龟产卵服务准备就绪:
            如果 自我.乌龟产卵:
                # 查找 target_frame 和 turtle2 框架之间的变换
                # 为乌龟 2 发送速度指令,使其到达目标帧
                尝试:
                    t = 自我.tf_buffer.查找变换(
                        至框架关系,
                        从帧关系,
                        rclpy.时间.时间())
                除开 转换异常 作为 :
                    自我.get_logger().信息(
                        f'无法转换 {至框架关系}{从帧关系}: {}')
                    返回

                信息 = 扭转()
                比例旋转率 = 1.0
                信息.角度.z = 比例旋转率 * 算术.atan2(
                    t..译文.y,
                    t..译文.x)

                前向速度 = 0.5
                信息.线形.x = 前向速度 * 算术.平方(
                    t..译文.x ** 2 +
                    t..译文.y ** 2)

                自我.出版商.发布(信息)
            不然:
                如果 自我.结果.完成的():
                    自我.get_logger().信息(
                        f'成功生成 {自我.结果.结果().名字}')
                    自我.乌龟产卵 = 正确
                不然:
                    自我.get_logger().信息(';再生侠尚未完成';)
        不然:
            如果 自我.产卵器.服务已就绪():
                # 用乌龟名称和坐标初始化请求
                # 注意,x、y 和 theta 在 turtlesim/srv/Spawn 中定义为浮点数
                要求 = 再生.要求()
                要求.名字 = 'turtle2';
                要求.x = 浮动(4)
                要求.y = 浮动(2)
                要求.θ = 浮动(0)
                # 呼叫请求
                自我.结果 = 自我.产卵器.调用同步(要求)
                自我.乌龟产卵服务准备就绪 = 正确
            不然:
                # 检查服务是否准备就绪
                自我.get_logger().信息('服务尚未准备就绪';)


捍卫 主要():
    rclpy.启动()
    网站 = 帧监听器()
    尝试:
        rclpy.后旋(网站)
    除开 键盘中断:
        通过

    rclpy.关闭()

1.1 检查代码

要了解产卵龟背后的服务是如何运作的,请参阅 编写简单的服务和客户端(Python) 教程。

现在,让我们来看看访问帧变换的相关代码。代码 tf2_ros 包提供了一个 变换监听器 来简化接收转换的工作。

 tf2_ros.transform_listener 舶来品 变换监听器

在这里,我们创建一个 变换监听器 对象。一旦创建了监听器,它就会开始通过线路接收 tf2 变换,并将其缓冲长达 10 秒。

自我.tf_listener = 变换监听器(自我.tf_buffer, 自我)

最后,我们向监听器查询特定的转换。我们调用 查找变换 方法,参数如下

  1. 目标框架

  2. 来源框架

  3. 我们希望转换的时间

提供 rclpy.time.Time() 将只获取最新的可用变换。所有这些都包裹在一个 try-except 块中,以处理可能出现的异常。

t = 自我.tf_buffer.查找变换(
    至框架关系,
    从帧关系,
    rclpy.时间.时间())

1.2 添加入口

玫瑰2 运行 命令来运行您的节点,您必须将入口点添加到 setup.py 位于 src/learning_tf2_py 目录)。

控制台脚本 括号:

'turtle_tf2_listener = learning_tf2_py.turtle_tf2_listener:main';,

2 更新启动文件

打开名为 turtle_tf2_demo_launch.pysrc/learning_tf2_py/launch 目录下,在启动说明中添加两个新节点,添加一个启动参数,并添加导入。生成的文件应该如下所示

 启动 舶来品 启动说明
 launch.actions 舶来品 声明启动参数
 launch.substitutions 舶来品 启动配置

 launch_ros.actions 舶来品 节点


捍卫 生成发射描述():
    返回 启动说明([
        节点(
            包装='turtlesim';,
            可执行='turtlesim_node',
            名字='sim';
        ),
        节点(
            包装='learning_tf2_py',
            可执行='turtle_tf2_broadcaster';,
            名字='broadcaster1',
            参数=[
                {'turtlename';: 'turtle1';}
            ]
        ),
        声明启动参数(
            'target_frame', 默认值='turtle1';,
            描述='目标帧名称;
        ),
        节点(
            包装='learning_tf2_py',
            可执行='turtle_tf2_broadcaster';,
            名字='broadcaster2',
            参数=[
                {'turtlename';: 'turtle2';}
            ]
        ),
        节点(
            包装='learning_tf2_py',
            可执行='turtle_tf2_listener',
            名字='听众';,
            参数=[
                {'target_frame': 启动配置('target_frame')}
            ]
        ),
    ])

这将声明一个 target_frame 启动参数,为我们将生成的第二只海龟启动广播器,并启动监听器来订阅这些转换。

3 建

运行 rosdep 在工作区的根目录下,检查是否存在缺失的依赖项。

rosdep install -i --from-path src --rosdistro jazzy -y

还是在工作区的根目录下,构建你的软件包:

colcon build --packages-select learning_tf2_py

打开一个新终端,导航到工作区的根目录,然后获取设置文件:

install/setup.bash

4 运行

现在你可以开始完整的乌龟演示了:

ros2 launch learning_tf2_py turtle_tf2_demo_launch.py

你会看到海龟模拟器上有两只海龟。在第二个终端窗口中键入以下命令:

ros2 run turtlesim turtle_teleop_key

要查看是否正常,只需使用箭头键绕过第一只乌龟(确保终端窗口处于活动状态,而不是模拟器窗口),就会看到第二只乌龟跟在第一只乌龟后面!

摘要

在本教程中,您学会了如何使用 tf2 访问帧变换。您还完成了自己编写的 turtlesim 演示,该演示在 tf2 简介 教程。