在类中使用参数 (Python) [待校准@9249]

Goal目标: using使用Python (rclpy) 创建并运行具有ROS参数的类。 [待校准@9250]

教程级别: 初学者 [Alyssa@7088]

Time时间: 20 20分钟 [待校准@7181]

背景

当你制作自己的 nodes 时,你有时需要添加可以从launch文件中设置的参数。 [待校准@9211]

本教程将向您展示如何在Python类中创建这些参数,以及如何在launch文件中设置它们。 [待校准@9251]

先决条件

在之前的教程中,您学习了如何在ROS 2系统中使用 create a workspace and create a package. You have also learned about parameters 及其功能。 [待校准@9213]

任务

1创建包

打开一个新的终端和 source your ROS 2 installation ,这样 ros2 命令就可以工作了。 [待校准@9214]

导航到 dev_ws 目录创建 previous tutorial[待校准@9215]

重新调用应该在 src 目录中创建的包,而不是工作区的根目录。导航到 dev_ws/src 并创建一个新的包: [待校准@9216]

ros2 pkg create --build-type ament_python python_parameters --dependencies rclpy

您的终端将返回一条消息,验证您的包 python_parameters 及其所有必要的文件和文件夹的创建。 [待校准@9252]

[需手动修复的语法] --dependencies 参数将自动调用y向 package.xmlCMakeLists.txt 添加必要的依赖线。 [待校准@9218]

1.1更新 package.xml [待校准@8003]

因为您在包创建过程中使用了 --dependencies 选项,所以您不必手动向 package.xmlCMakeLists.txt 添加依赖项。 [待校准@9219]

但是,与往常一样,请确保将描述、维护人员电子邮件和姓名以及许可信息添加到 package.xml[待校准@9220]

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

2编写Python节点 [待校准@9253]

dev_ws/src/python_parameters/python_parameters 目录内,创建一个调用 python_parameters_node.py 的新文件,并将以下代码粘贴到: [待校准@9254]

import rclpy
import rclpy.node

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')
        timer_period = 2  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)

        self.declare_parameter('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)

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

if __name__ == '__main__':
    main()

2.1检查代码 [待校准@8007]

注意: 在获取或设置参数之前声明参数是强制性的,否则将引发 ParameterNotDeclaredException 异常。 [待校准@9255]

下面的 import 语句用于导入包依赖关系。 [待校准@9256]

import rclpy
import rclpy.node

下一段代码创建类和构造函数。 timer 被初始化 (定时器周期设置为2秒),这导致 timer_callback 函数每两秒执行一次。构造函数的行 “self.Decare_parameter ('my_parameter','world')” 创建一个名称为 my_parameter 的参数,默认值为 world 。参数类型是从默认值中推断出的,因此在这种情况下,它将被设置为string类型。 [待校准@9257]

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')
        timer_period = 2  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)

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

我们的 timer_callback 函数的第一行从节点获取参数 my_parameter ,并将其存储在 my_param 中。接下来, get_logger 函数确保消息被记录。的 set_parameters 函数设置参数 my_parameter 回到默认string阀门 world 。在用户外部更改参数的情况下,这可确保始终将其重置回原始参数。 [待校准@9258]

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 是ROS 2初始化的 main 函数。然后定义了一个名为 nodeMinimalParam 类实例。最后, rclpy.spin 从节点开始处理数据。 [待校准@9259]

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

if __name__ == '__main__':
    main()
2.1.1 (可选) 添加参数描述符 [待校准@9260]

您可以选择为参数设置描述符。描述符允许您指定参数和参数约束的文本描述,例如使其成为只读、指定范围等。为此, __init__ 代码必须更改为: [待校准@9261]

# ...

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')
        timer_period = 2  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)

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

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

其余代码保持不变。运行节点后,您可以运行 ros2 param describe /minimal_param_node my_parameter 来查看类型和描述。 [待校准@9262]

2.2添加入口点 [待校准@9263]

打开 setup.py 文件。再一次,将 maintainermaintainer_emaildescriptionlicense 田地与你的 package.xml 相匹配: [待校准@9264]

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

添加以下内 console_scripts 支架的 entry_points 领域: [待校准@9265]

entry_points={
    'console_scripts': [
        'param_talker = python_parameters.python_parameters_node:main',
    ],
},

不要忘记保存。 [待校准@9266]

3构建和运行 [待校准@8033]

在构建之前,最好在工作区 ( dev_ws ) 的根目录下运行 rosdep ,以检查是否缺少依赖项: [待校准@9228]

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

导航回工作区的根目录, dev_ws ,并构建新的包: [待校准@9230]

colcon build --packages-select python_parameters

打开一个新的终端,导航到 dev_ws ,源文件安装文件: [待校准@9231]

. install/setup.bash

现在运行节点: [待校准@7899]

ros2 run python_parameters param_talker

终端应每2秒返回以下消息: [待校准@9267]

[INFO] [parameter_node]: Hello world!

有两种方法可以更改参数: [待校准@9268]

3.1通过控制台进行更改 [待校准@9234]

这部分将使用你从 tutoral about parameters 中获得的知识,并将其应用到你刚刚创建的节点上。 [待校准@9269]

确保节点正在运行: [待校准@9236]

ros2 run python_parameters param_talker

打开另一个终端,再次从 dev_ws 内部源文件,然后输入以下行: [待校准@9237]

ros2 param list

在那里你会看到自定义参数 my_parameter 。要更改它,只需在控制台中运行以下行: [待校准@9238]

ros2 param set /minimal_param_node my_parameter earth

你知道如果你得到输出 Set parameter successful ,一切都很顺利。如果您查看另一个终端,您应该会看到输出更改为 “[信息] [minimal_param_node]: Hello earth!” [待校准@9270]

由于Python talker随后将参数设置回 world ,进一步的输出显示 “[信息] [最小 _ 参数 _ 节点]: 你好,世界!” [待校准@9271]

3.2通过launch文件进行更改 [待校准@9240]

您也可以在launch文件中设置参数,但是首先您需要添加一个launch目录。在 dev_ws/src/python_parameters/ 目录内,创建一个调用 launch 的新目录。在那里,创建一个调用ed python_parameters_launch.py 的新文件 [待校准@9272]

from launch import LaunchDescription
from launch_ros.actions import Node

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

在这里你可以看到,当我们将节点 parameter_node launch时,我们将 my_parameter 设置为 earth 。通过添加下面的两行,我们确保我们的输出打印在我们的控制台中。 [待校准@9242]

output="screen",
emulate_tty=True,

现在打开 setup.py 文件。将 import 语句添加到文件顶部,将另一个新语句添加到 data_files 参数中,以包括所有launch文件: [待校准@9273]

import os
from glob import glob
# ...

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

打开控制台,导航到工作区的根目录, dev_ws ,然后构建新包: [待校准@9244]

colcon build --packages-select python_parameters

然后在新终端中源文件安装文件: [待校准@9245]

. install/setup.bash

现在使用我们刚刚创建的launch文件运行该节点: [待校准@9246]

ros2 launch python_parameters python_parameters_launch.py

终端应返回以下消息: [待校准@9274]

[parameter_node-1] [INFO] [custom_parameter_node]: Hello earth!

总结

您使用自定义参数创建了一个节点,可以从launch文件或命令行中设置该参数。您编写了一个参数谈话者的代码: 一个Python节点,它声明,然后循环获取和设置一个string参数。您添加了入口点,以便构建和运行它,并使用 ros2 param 与参数谈话者进行交互。 [待校准@9275]

下一步

既然你有了自己的包和ROS 2系统, next tutorial 将向你展示如何检查你的环境和系统中的问题,以防你有问题。 [待校准@9248]