【ROS2】中级-监控参数变化(Python)

目标:学习使用 ParameterEventHandler 类来监控和响应参数变化。

教程级别:中级

 时间:20 分钟

 目录

  •  背景

  •  先决条件

  •  任务

    • 1. 创建一个包

    • 2. 编写 Python 节点

    • 3. 建立并运行

  •  摘要

  •  相关内容

 背景

经常有节点需要响应其自身参数或其他节点参数的变化。ParameterEventHandler 类使得监听参数变化变得简单,以便您的代码可以对它们做出响应。本教程将向您展示如何使用 ParameterEventHandler 类的 Python 版本来监控节点自身参数的变化以及其他节点参数的变化

 先决条件

在开始本教程之前,您应该先完成以下教程:

  •  理解参数 https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Parameters/Understanding-ROS2-Parameters.html 

  • 在类中使用参数(Python) https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Using-Parameters-In-A-Class-Python.html

 任务

在本教程中,您将创建一个新的包来包含一些示例代码,编写一些 Python 代码来使用 ParameterEventHandler 类,并测试结果代码。

1. 创建一个包

首先,打开一个新的终端并且配置你的 ROS 2 安装,以便 ros2 命令能够工作。

按照这些指示创建一个名为 ros2_ws 的新工作区。

请记住,包应该在 src 目录中创建,而不是在工作区的根目录中。因此,请导航到 ros2_ws/src ,然后在那里创建一个新包:

ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameter_event_handler --dependencies rclpy

您的终端将返回一条消息,确认您的包 python_parameter_event_handler 及其所有必要的文件和文件夹已创建。

--dependencies `参数将自动向` package.xml `和` CMakeLists.txt `添加必要的依赖行。

cxy@ubuntu2404-cxy:~/ros2_ws/src$ ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameter_event_handler --dependencies rclpy
going to create a new package
package name: python_parameter_event_handler
destination directory: /home/cxy/ros2_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['cxy <cxy@todo.todo>']
licenses: ['Apache-2.0']
build type: ament_python
dependencies: ['rclpy']
creating folder ./python_parameter_event_handler
creating ./python_parameter_event_handler/package.xml
creating source folder
creating folder ./python_parameter_event_handler/python_parameter_event_handler
creating ./python_parameter_event_handler/setup.py
creating ./python_parameter_event_handler/setup.cfg
creating folder ./python_parameter_event_handler/resource
creating ./python_parameter_event_handler/resource/python_parameter_event_handler
creating ./python_parameter_event_handler/python_parameter_event_handler/__init__.py
creating folder ./python_parameter_event_handler/test
creating ./python_parameter_event_handler/test/test_copyright.py
creating ./python_parameter_event_handler/test/test_flake8.py
creating ./python_parameter_event_handler/test/test_pep257.py
 1.1 更新 package.xml 

因为您在创建包时使用了 --dependencies 选项,您无需手动将依赖项添加到 package.xml 中。但是,一如既往,请确保将描述、维护者电子邮件和姓名以及许可信息添加到 package.xml 中。

<description>Python parameter events client tutorial</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache-2.0</license>

2. 编写 Python 节点

在 ros2_ws/src/python_parameter_event_handler/python_parameter_event_handler 目录中,创建一个名为 parameter_event_handler.py 的新文件,并将以下代码粘贴其中:

cxy@ubuntu2404-cxy:~/ros2_ws/src/python_parameter_event_handler/python_parameter_event_handler$ gedit parameter_event_handler.py

227c8f81b7ff6cd7c1aef1b9d557cd7a.png

import rclpy  # 导入rclpy模块,ROS2的Python库
import rclpy.node  # 导入rclpy.node模块,用于创建ROS2节点
import rclpy.parameter  # 导入rclpy.parameter模块,用于处理ROS2参数


from rclpy.parameter_event_handler import ParameterEventHandler  # 从rclpy.parameter_event_handler模块导入ParameterEventHandler类,用于处理参数事件




class SampleNodeWithParameters(rclpy.node.Node):  # 定义一个名为SampleNodeWithParameters的类,继承自rclpy.node.Node
    def __init__(self):  # 类的初始化函数
        super().__init__('node_with_parameters')  # 调用父类的初始化函数,创建一个名为'node_with_parameters'的节点


        self.declare_parameter('an_int_param', 0)  # 声明一个名为'an_int_param'的参数,初始值为0


        self.handler = ParameterEventHandler(self)  # 创建一个ParameterEventHandler对象,用于处理参数事件


        self.callback_handle = self.handler.add_parameter_callback(  # 添加一个参数回调函数
            parameter_name="an_int_param",  # 参数名为'an_int_param'
            node_name="node_with_parameters",  # 节点名为'node_with_parameters'
            callback=self.callback,  # 回调函数为self.callback
        )


    def callback(self, p: rclpy.parameter.Parameter) -> None:  # 定义回调函数
        self.get_logger().info(f"Received an update to parameter: {p.name}: {rclpy.parameter.parameter_value_to_python(p.value)}")  # 在日志中记录参数更新的信息




def main():  # 定义主函数
    rclpy.init()  # 初始化ROS2
    node = SampleNodeWithParameters()  # 创建SampleNodeWithParameters对象
    rclpy.spin(node)  # 使节点保持活动状态,直到被中断或关闭
    rclpy.shutdown()  # 关闭ROS2
2.1 检查代码 

顶部的 import 语句用于导入包依赖项。

import rclpy
import rclpy.node
import rclpy.parameter


from rclpy.parameter_event_handler import ParameterEventHandler

下一段代码创建了类 SampleNodeWithParameters 和构造函数。该类的构造函数声明了一个整数参数 an_int_param ,默认值为 0。接下来,代码创建了一个 ParameterEventHandler ,用于监控参数的变化。

class SampleNodeWithParameters(rclpy.node.Node):
    def __init__(self):
        super().__init__('node_with_parameters')


        self.declare_parameter('an_int_param', 0)


        self.handler = ParameterEventHandler(self)

最后,我们添加参数回调并获取新回调的回调处理程序。

 便条

保存由 add_parameter_callback 返回的句柄非常重要;否则,回调将无法正确注册。

self.callback_handle = self.handler.add_parameter_callback(
    parameter_name="an_int_param",
    node_name="node_with_parameters",
    callback=self.callback,
)

对于回调函数,我们使用 SampleNodeWithParameters 类的 callback 方法。

def callback(self, p: rclpy.parameter.Parameter) -> None:
    self.get_logger().info(f"Received an update to parameter: {p.name}: {rclpy.parameter.parameter_value_to_python(p.value)}")

跟随 SampleNodeWithParameters 是一个典型的 main 函数,它初始化 ROS,旋转样本节点以便它可以发送和接收消息,然后在用户在控制台输入^C 之后关闭。

def main():
    rclpy.init()
    node = SampleNodeWithParameters()
    rclpy.spin(node)
    rclpy.shutdown()
2.2 添加一个入口点 

打开 setup.py 文件。再次,将 maintainer 、 maintainer_email 、 description 和 license 字段与您的 package.xml 匹配:

maintainer='YourName',
maintainer_email='you@email.com',
description='Python parameter tutorial',
license='Apache-2.0',

在 entry_points 字段的 console_scripts 括号内添加以下行:

entry_points={
    'console_scripts': [
        'node_with_parameters = python_parameter_event_handler.parameter_event_handler:main',
    ],
},

d672acf5c76de48c73c647907e4b7f01.png

3. 构建并运行

在工作区的根目录运行 rosdep ( ros2_ws )以检查构建前缺失的依赖项是一个好习惯:

rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y

返回到您的工作区根目录, ros2_ws ,然后构建您的新包:

cxy@ubuntu2404-cxy:~/ros2_ws$ colcon build --packages-select python_parameter_event_handler
Starting >>> python_parameter_event_handler
Finished <<< python_parameter_event_handler [6.80s]          


Summary: 1 package finished [7.58s]

打开一个新的终端,导航到 ros2_ws ,并且导入设置文件:

. install/setup.bash

现在运行节点:

ros2 run python_parameter_event_handler node_with_parameters

节点现在已激活,具有单一参数,并将在此参数更新时打印消息。为了测试这一点,请打开另一个终端,像以前一样加载 ROS 设置文件,然后执行以下命令:

ros2 param set node_with_parameters an_int_param 43

78ad073628d9a708879ab4eca5b8b42f.png

运行节点的终端将显示类似于以下的消息:

[INFO] [1698483083.315084660] [node_with_parameters]: Received an update to parameter: an_int_param: 43

我们之前在节点中设置的回调函数已被调用,并显示了新的更新值。您现在可以使用终端中的 ^C 终止正在运行的 parameter_event_handler 示例。

3.1 监视另一节点参数的变化

您也可以使用 ParameterEventHandler 来监控对另一个节点参数的更改。让我们更新 SampleNodeWithParameters 类,以监控另一个节点中参数的变化。我们将使用 parameter_blackboard 演示应用程序来托管一个双参数,我们将监控其更新。

首先更新构造函数,将以下代码添加到现有代码之后:

def __init__(...):
    ...
    self.callback_handle = self.handler.add_parameter_callback(
        parameter_name="a_double_param",
        node_name="parameter_blackboard",
        callback=self.callback,
    )

在终端中,导航回到您的工作区根目录, ros2_ws ,然后像以前一样构建您的更新包:

colcon build --packages-select python_parameter_event_handler
cxy@ubuntu2404-cxy:~/ros2_ws$ colcon build --packages-select python_parameter_event_handler
Starting >>> python_parameter_event_handler
Finished <<< python_parameter_event_handler [2.45s]          


Summary: 1 package finished [2.69s]

然后获取设置文件:

. install/setup.bash

现在,为了测试远程参数的监控,请首先运行新构建的 parameter_event_handler 代码:

ros2 run python_parameter_event_handler node_with_parameters

接下来,在另一个已初始化 ROS 的终端中,运行 parameter_blackboard 演示应用程序,如下:

ros2 run demo_nodes_cpp parameter_blackboard

最后,在第三个终端(已初始化 ROS),让我们在 parameter_blackboard 节点上设置一个参数:

ros2 param set parameter_blackboard a_double_param 3.45

执行此命令后,您应该会在 parameter_event_handler 窗口中看到输出,表明在参数更新时调用了回调函数:

[INFO] [1699821958.757770223] [node_with_parameters]: Received an update to parameter: a_double_param: 3.45

14906ede1b61562453b9511552d47053.png

 摘要

您创建了一个带有参数的节点,并使用 ParameterEventHandler 类设置了一个回调来监视该参数的变化。您还使用同一个类来监视远程节点的变化。ParameterEventHandler 是一种监控参数变化的便捷方式,以便您可以对更新后的值做出响应。

 相关内容 

要了解如何将 ROS 1 参数文件适配到 ROS 2,请参阅从 ROS 1 到 ROS 2 迁移 YAML 参数文件的教程。https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-Parameters.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值