Skip to content

徒手搓出来一个ROS2的Python节点

上节课,我们是利用模板的方式创建了一个ROS2的Python节点,今天我们来徒手搓出来一个ROS2的Python节点。

徒手搓出来的节点和模板创建的节点是一样的,只是我们手动创建了文件夹和文件(所以我们上节课要了解一下ROS2包的结构)。

利用Python手搓ament_python节点的基本流程如下:

  1. 修改package.xml以添加任何额外的依赖项。
  2. 创建节点(node)。
  3. 修改setup.py文件。

让我们向我们的ament_python包中添加一个额外的节点,该节点实际上使用了 ROS2 功能。以下是通常需要采取的步骤,以添加一个新节点。

处理依赖项

package.xml 是由 ros2 pkg create 自动生成的,包含了关于包的基本信息。

package.xml 的一个重要作用是声明与其他 ROS2 包的依赖关系。新节点通常会有额外的依赖项,因此我们将在这里讨论这一点。对于任何 ROS2 包,我们必须修改 package.xml 以添加新的依赖项。

在这个简单的示例中,让我们添加rclpy作为依赖项,因为它是RCL的 Python 实现。所有使用与 ROS2 相关的任何内容的节点都将直接或间接依赖于该库。并非巧合,package.xml 文件具有 .xml 扩展名,这意味着它是用 XML 编写的。

让我们在<license><test_depend>标签之间添加依赖关系。这不是一个严格的要求,但通常是标准包中的常见做法。

xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>python_package_with_a_node</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="[email protected]">murilo</maintainer>
  <license>TODO: License declaration</license>

  <depend>rclpy</depend>

  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend>
  <test_depend>python3-pytest</test_depend>

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>

重新构建工作区

在将新依赖项添加到package.xml后,除非执行新的构建,否则工作区中实际上没有任何变化。

zsh
cd ~/ros2_tutorial_workspace
colcon build
source install/setup.zsh

创建节点

在目录 src/python_package_with_a_node/python_package_with_a_node 中,创建一个名为python_node.py的文件。我们将把节点的代码放在这里。

Python
import rclpy
from rclpy.node import Node


def main():
    rclpy.init()
    node = Node("python_node")
    node.get_logger().info("Hello from Python Node!")
    rclpy.spin(node)
    rclpy.shutdown()

修改setup.py

为了能让功能包python_package_with_a_node找到这个节点,我们需要在setup.py中添加一些入口信息。在src/python_package_with_a_node/setup.py中,添加以下内容:

Python
from setuptools import find_packages, setup

package_name = 'python_package_with_a_node'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='kyle',
    maintainer_email='[email protected]',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'sample_python_node = python_package_with_a_node.sample_python_node:main',
            'python_node = python_package_with_a_node.python_node:main',
        ],
    },
)

注意:上述代码的第24行,就是通知ROS2关于节点python_node的程序启动入口。

运行节点

再次构建工作区,并加载环境变量:

zsh
cd ~/ros2_tutorial_workspace
colcon build
source install/setup.zsh

然后运行节点:

zsh
ros2 run python_package_with_a_node python_node

这将输出:

zsh
[INFO] [1742282609.323775524] [python_node]: Hello from Python Node!

课堂自学环节

本堂课大家照猫画虎地利用我们提供的Python代码,熟练了解了ROS2的Python节点的创建流程后,大家可以尝试自己创建一个ROS2的Python节点,完成以下任务:

  1. 利用我们的AI助手,解读python_node.py的代码含义。
  2. 创建一个新的节点,命名为my_python_node
  3. 利用节点,循环打印从1到100的数字。

如果不借助我们的AI助手,嗯,估计您应该没法手搓出来这个功能,所以我们需要学习一些Python的基本编程知识。

我们以前提供了一个Python编程的学习路线图,大家可以参考一下: 02. 最低限度的Python知识技能

关于Python教材嘛?我认为这个系列教程是面向初学者的很好的参考: Python 基础教程

共性的问题我会在本堂自学环节统一解惑。

Action! Go Go Go!

总结

在本节中,我们学习了如何徒手搓出来一个ROS2的Python节点:

  1. 我们创建了一个新的节点,并将其添加到python_package_with_a_node包中。
  2. 我们还学习了如何修改package.xml以添加依赖项,
  3. 以及如何在setup.py中添加节点的入口点。
  4. 我们还复习了如何使用ros2 run命令运行节点。
  5. 自学环节中,大家尝试创建了一个新的节点my_python_node,并利用节点循环打印从1到100的数字。

在下一节中,我们将学习如何使用rclpy库中的其他功能来创建更复杂的节点。