在类中使用参数(Python)

目标:使用 Python 创建并运行带有 ROS 参数的类。

教程级别:初学者

时间:20 分钟

背景

在制作自己的 节点 时,有时需要添加可从启动文件中设置的参数。

本教程将向您展示如何在 Python 类中创建这些参数,以及如何在启动文件中设置它们。

先决条件

在之前的教程中,您学习了如何 创建工作区创建包

您还了解了 参数 及其在 RO​​S 2 系统中的功能。

任务

1 创建一个包

打开一个新终端并 source your ROS 2 installation,以便 ros2 命令可以正常工作。

按照 these instructions 创建一个名为 ros2_ws 的新工作区。

回想一下,应该在 src 目录中创建包,而不是在工作区的根目录中创建包。 导航到 ros2_ws/src 并创建一个新包:

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

您的终端将返回一条消息,验证您的包“python_parameters”及其所有必要的文件和文件夹的创建。

“–dependencies”参数将自动将必要的依赖项行添加到“package.xml”和“CMakeLists.txt”中。

1.1 更新“package.xml”

由于您在包创建期间使用了“–dependencies”选项,因此您不必手动将依赖项添加到“package.xml”或“CMakeLists.txt”中。

不过,与往常一样,请确保将描述、维护者电子邮件和姓名以及许可证信息添加到“package.xml”中。

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

2 编写 Python 节点

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

import rclpy
import rclpy.node

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        self.declare_parameter('my_parameter', 'world')

        self.timer = self.create_timer(1, self.timer_callback)

    def timer_callback(self):
        my_param = self.get_parameter('my_parameter').get_parameter_value().string_value

        self.get_logger().info('Hello %s!' % my_param)

        my_new_param = rclpy.parameter.Parameter(
            'my_parameter',
            rclpy.Parameter.Type.STRING,
            'world'
        )
        all_new_parameters = [my_new_param]
        self.set_parameters(all_new_parameters)

def main():
    rclpy.init()
    node = MinimalParam()
    rclpy.spin(node)

if __name__ == '__main__':
    main()

2.1 检查代码

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

下一段代码创建类和构造函数。 构造函数的行 self.declare_parameter('my_parameter', 'world') 创建一个名为 my_parameter 的参数,默认值为 world。 参数类型是从默认值推断出来的,因此在本例中它将被设置为字符串类型。 接下来,使用周期 1 初始化 timer,这会导致 timer_callback 函数每秒执行一次。

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        self.declare_parameter('my_parameter', 'world')

        self.timer = self.create_timer(1, self.timer_callback)

我们的 timer_callback 函数的第一行从节点获取参数 my_parameter,并将其存储在 my_param 中。 接下来,get_logger 函数确保记录事件。 然后,set_parameters 函数将参数 my_parameter 设置回默认字符串值 world。 如果用户从外部更改了参数,这可确保始终将其重置回原始值。

def timer_callback(self):
    my_param = self.get_parameter('my_parameter').get_parameter_value().string_value

    self.get_logger().info('Hello %s!' % my_param)

    my_new_param = rclpy.parameter.Parameter(
        'my_parameter',
        rclpy.Parameter.Type.STRING,
        'world'
    )
    all_new_parameters = [my_new_param]
    self.set_parameters(all_new_parameters)

timer_callback 之后是我们的 main。 这里初始化 ROS 2,构造 MinimalParam 类的实例,并且 rclpy.spin 开始处理来自节点的数据。

def main():
    rclpy.init()
    node = MinimalParam()
    rclpy.spin(node)

if __name__ == '__main__':
    main()
2.1.1 (可选)添加参数描述符

或者,您可以为参数设置描述符。 描述符允许您指定参数及其约束的文本描述,例如使其只读、指定范围等。 为了使其工作,必须将 __init__ 代码更改为:

# ...

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        from rcl_interfaces.msg import ParameterDescriptor
        my_parameter_descriptor = ParameterDescriptor(description='This parameter is mine!')

        self.declare_parameter('my_parameter', 'world', my_parameter_descriptor)

        self.timer = self.create_timer(1, self.timer_callback)

其余代码保持不变。 运行节点后,您可以运行“ros2 param describe /minimal_param_node my_parameter”来查看类型和描述。

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': [
        'minimal_param_node = python_parameters.python_parameters_node:main',
    ],
},

别忘了保存。

3 构建并运行

在构建之前,最好在工作区 (ros2_ws) 的根目录中运行 rosdep 来检查缺少的依赖项:

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

导航回到工作区的根目录“ros2_ws”,并构建新的包:

colcon build --packages-select python_parameters

打开一个新终端,导航到“ros2_ws”,并获取安装文件:

source install/setup.bash

现在运行节点:

ros2 run python_parameters minimal_param_node

终端应每秒返回以下消息:

[INFO] [parameter_node]: Hello world!

现在您可以看到参数的默认值,但您希望能够自己设置它。 有两种方法可以实现这一点。

3.1 通过控制台更改

本部分将使用您从 tutoral about parameters 获得的知识并将其应用于您刚刚创建的节点。

确保节点正在运行:

ros2 run python_parameters minimal_param_node

打开另一个终端,再次从“ros2_ws”内部获取安装文件,然后输入以下行:

ros2 param list

您将在那里看到自定义参数“my_parameter”。 要更改它,只需在控制台中运行以下行:

ros2 param set /minimal_param_node my_parameter earth

如果输出“设置参数成功”,则表明一切顺利。

如果查看另一个终端,则应该看到输出更改为“[INFO] [minimal_param_node]: Hello earth!”

由于节点随后将参数设置回“world”,因此进一步的输出显示“[INFO] [minimal_param_node]: Hello world!”

3.2 通过启动文件进行更改

您也可以在启动文件中设置参数,但首先需要添加启动目录。

在“ros2_ws/src/python_parameters/”目录中,创建一个名为“launch”的新目录。

在其中,创建一个名为“python_parameters_launch.py​​”的新文件

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='python_parameters',
            executable='minimal_param_node',
            name='custom_minimal_param_node',
            output='screen',
            emulate_tty=True,
            parameters=[
                {'my_parameter': 'earth'}
            ]
        )
    ])

在这里你可以看到,当我们启动我们的节点“parameter_node”时,我们将“my_parameter”设置为“earth”。 通过添加下面两行,我们确保我们的输出打印在我们的控制台中。

output="screen",
emulate_tty=True,

现在打开“setup.py”文件。 将“import”语句添加到文件顶部,并将另一个新语句添加到“data_files”参数以包含所有启动文件:

import os
from glob import glob
# ...

setup(
  # ...
  data_files=[
      # ...
      (os.path.join('share', package_name), glob('launch/*launch.[pxy][yma]*')),
    ]
  )

打开控制台并导航到工作区的根目录“ros2_ws”,然后构建新包:

colcon build --packages-select python_parameters

然后在新终端中获取安装文件:

source install/setup.bash

现在使用我们刚刚创建的启动文件运行节点:

ros2 launch python_parameters python_parameters_launch.py

终端第一次应该返回以下消息:

[INFO] [custom_minimal_param_node]: Hello earth!

进一步的输出应该每秒显示“[INFO] [minimal_param_node]: Hello world!”。

摘要

您创建了一个具有自定义参数的节点,该参数可以从启动文件或命令行进行设置。

您将依赖项、可执行文件和启动文件添加到包配置文件中,以便您可以构建和运行它们,并查看参数的实际作用。

后续步骤

现在您有了一些自己的包和 ROS 2 系统,下一个教程 将向您展示如何在遇到问题时检查您的环境和系统中的问题。