Skip to content

创建第一个 ROS 2 包

目标: 使用 CMake 或 Python 创建一个新包,并运行其可执行文件。

教程级别: 初级

预计用时: 15 分钟

包是 ROS 2 代码的组织单元。如果你希望能够安装你的代码或与他人分享,就需要将其组织成包。通过包,你可以发布你的 ROS 2 作品,并让其他人轻松地构建和使用它。

ROS 2 使用 ament 作为构建系统,使用 colcon 作为构建工具。你可以使用 CMake 或 Python 创建包,这两种方式都是官方支持的,不过也存在其他构建类型。

ROS 2 的 Python 和 CMake 包各自有最低要求的文件内容:

CMake

  • CMakeLists.txt 文件,描述如何构建包内的代码
  • include/<package_name> 目录,包含包的公共头文件
  • package.xml 文件,包含包的元信息
  • src 目录,包含包的源代码

Python

  • package.xml 文件,包含包的元信息
  • resource/<package_name> 标记文件
  • setup.cfg,当包有可执行文件时需要此文件,这样 ros2 run 才能找到它们
  • setup.py,包含如何安装包的说明
  • <package_name> — 与包同名的目录,ROS 2 工具通过它来找到你的包,包含 __init__.py

最简单的包可能具有如下文件结构:

CMake

Terminal window
my_package/
CMakeLists.txt
include/my_package/
package.xml
src/

Python

Terminal window
my_package/
package.xml
resource/my_package
setup.cfg
setup.py
my_package/

一个工作空间可以包含任意数量的包,每个包都在自己的文件夹中。你还可以在一个工作空间中拥有不同构建类型的包(CMake、Python 等)。但不能有嵌套的包。

最佳实践是在工作空间内使用一个 src 文件夹,并在其中创建你的包。这样可以保持工作空间顶层”干净”。

一个简单的工作空间可能如下所示:

Terminal window
workspace_folder/
src/
cpp_package_1/
CMakeLists.txt
include/cpp_package_1/
package.xml
src/
py_package_1/
package.xml
resource/py_package_1
setup.cfg
setup.py
py_package_1/
...
cpp_package_n/
CMakeLists.txt
include/cpp_package_n/
package.xml
src/

按照上一个教程中的说明操作后,你应该已经拥有一个 ROS 2 工作空间。你将在这个工作空间中创建你的包。

首先,source 你的 ROS 2 安装环境。

使用你在上一个教程中创建的工作空间 ros2_ws 来创建你的新包。

在运行包创建命令之前,请确保你在 src 文件夹中。

Linux

Terminal window
$ cd ~/ros2_ws/src

macOS

Terminal window
$ cd ~/ros2_ws/src

Windows

Terminal window
$ cd \ros2_ws\src

在 ROS 2 中创建新包的命令语法为:

CMake

Terminal window
$ ros2 pkg create --build-type ament_cmake --license Apache-2.0 <package_name>

Python

Terminal window
$ ros2 pkg create --build-type ament_python --license Apache-2.0 <package_name>

在本教程中,你将使用可选参数 --node-name 和 --license。--node-name 选项会在包中创建一个简单的 Hello World 类型可执行文件,--license 声明包的许可证信息。

在终端中输入以下命令:

CMake

Terminal window
$ ros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name my_node my_package

Python

Terminal window
$ ros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_node my_package

现在你的工作空间的 src 目录中将有一个名为 my_package 的新文件夹。

运行命令后,你的终端将返回以下消息:

CMake

Terminal window
going to create a new package
package name: my_package
destination directory: /home/user/ros2_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['<name> <email>']
licenses: ['Apache-2.0']
build type: ament_cmake
dependencies: []
node_name: my_node
creating folder ./my_package
creating ./my_package/package.xml
creating source and include folder
creating folder ./my_package/src
creating folder ./my_package/include/my_package
creating ./my_package/CMakeLists.txt
creating ./my_package/src/my_node.cpp

Python

Terminal window
going to create a new package
package name: my_package
destination directory: /home/user/ros2_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['<name> <email>']
licenses: ['Apache-2.0']
build type: ament_python
dependencies: []
node_name: my_node
creating folder ./my_package
creating ./my_package/package.xml
creating source folder
creating folder ./my_package/my_package
creating ./my_package/setup.py
creating ./my_package/setup.cfg
creating folder ./my_package/resource
creating ./my_package/resource/my_package
creating ./my_package/my_package/__init__.py
creating folder ./my_package/test
creating ./my_package/test/test_copyright.py
creating ./my_package/test/test_flake8.py
creating ./my_package/test/test_pep257.py
creating ./my_package/my_package/my_node.py

你可以看到新包自动生成的文件。

将包放在工作空间中的好处在于,你可以在工作空间根目录运行 colcon build 一次性构建多个包,而不必逐个构建。

返回到你的工作空间根目录:

Linux

Terminal window
$ cd ~/ros2_ws

macOS

Terminal window
$ cd ~/ros2_ws

Windows

Terminal window
$ cd \ros2_ws

现在你可以构建你的包了:

Linux

Terminal window
$ colcon build

macOS

Terminal window
$ colcon build

Windows

Terminal window
$ colcon build --merge-install

Windows 对路径长度有限制,因此 merge-install 会将所有路径合并到 install 目录中。

回想一下上一个教程,你的 ros2_ws 中还有 ros_tutorials 包。你可能已经注意到运行 colcon build 也构建了 turtlesim 包。当你的工作空间中只有少量包时这没问题,但当有很多包时,colcon build 可能需要很长时间。

要仅构建 my_package 包,你可以运行:

Terminal window
$ colcon build --packages-select my_package

要使用你的新包和可执行文件,首先打开一个新终端并 source 你的主 ROS 2 安装环境。

然后,在 ros2_ws 目录中运行以下命令来 source 你的工作空间:

Linux

Terminal window
$ source install/local_setup.bash

macOS

Terminal window
$ . install/local_setup.bash

Windows

Terminal window
$ call install/local_setup.bat

现在你的工作空间已添加到路径中,你将能够使用新包的可执行文件。

要运行你在创建包时使用 --node-name 参数创建的可执行文件,输入以下命令:

Terminal window
$ ros2 run my_package my_node

它将在你的终端返回一条消息:

CMake

Terminal window
hello world my_package package

Python

Terminal window
Hi from my_package.

在 ros2_ws/src/my_package 中,你将看到 ros2 pkg create 自动生成的文件和文件夹:

CMake

Terminal window
CMakeLists.txt include package.xml src

my_node.cpp 位于 src 目录中。这是你将来放置所有自定义 C++ 节点的地方。

Python

Terminal window
my_package package.xml resource setup.cfg setup.py test

my_node.py 位于 my_package 目录中。这是你将来放置所有自定义 Python 节点的地方。

你可能已经注意到,创建包后的返回消息中 description 和 license 字段包含 TODO 备注。这是因为包描述和许可证声明不会自动设置,但如果你想要发布包,这些是必填的。maintainer 字段也可能需要填写。

从 ros2_ws/src/my_package 中,使用你喜欢的文本编辑器打开 package.xml:

CMake

<?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>my_package</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="user@todo.todo">user</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>

Python

<?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>my_package</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="user@todo.todo">user</maintainer>
<license>TODO: License declaration</license>
<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>

如果 maintainer 行没有自动填充你的姓名和邮箱,请手动输入。然后,编辑 description 行来概括包的内容:

<description>Beginner client libraries tutorials practice package</description>

然后,更新 license 行。你可以在 这里 阅读更多关于开源许可证的信息。由于这个包仅用于练习,使用任何许可证都可以。我们将使用 Apache-2.0:

<license>Apache-2.0</license>

编辑完成后别忘了保存。

在 license 标签下方,你会看到一些以 _depend 结尾的标签名。这里用于声明对其他包的依赖关系,colcon 会搜索这些依赖。my_package 很简单,没有任何依赖,但在后续教程中你会在这里添加依赖。

CMake

你现在已经全部完成了!

Python

setup.py 文件包含与 package.xml 相同的 description、maintainer 和 license 字段,因此你也需要设置这些内容。它们在两个文件中必须完全匹配。版本和名称(package_name)也必须完全匹配,并且应该已经在两个文件中自动填充。

使用你喜欢的文本编辑器打开 setup.py。

from setuptools import find_packages, setup
package_name = 'my_py_pkg'
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='TODO',
maintainer_email='TODO',
description='TODO: Package description',
license='TODO: License declaration',
extras_require={
'test': ['pytest'],
},
entry_points={
'console_scripts': [
'my_node = my_py_pkg.my_node:main'
],
},
)

编辑 maintainer、maintainer_email 和 description 行,使其与 package.xml 匹配。

别忘了保存文件。

你已经创建了一个包来组织你的代码,并使其便于他人使用。

你的包自动生成了必要的文件,然后你使用 colcon 构建了它,这样你就可以在本地环境中使用其可执行文件。

接下来,为包添加一些有意义的内容。你将从简单的发布者/订阅者系统开始,可以选择用 C++ 或 Python 来编写。