创建第一个 ROS 2 包
目标: 使用 CMake 或 Python 创建一个新包,并运行其可执行文件。
教程级别: 初级
预计用时: 15 分钟
1 什么是 ROS 2 包?
Section titled “1 什么是 ROS 2 包?”包是 ROS 2 代码的组织单元。如果你希望能够安装你的代码或与他人分享,就需要将其组织成包。通过包,你可以发布你的 ROS 2 作品,并让其他人轻松地构建和使用它。
ROS 2 使用 ament 作为构建系统,使用 colcon 作为构建工具。你可以使用 CMake 或 Python 创建包,这两种方式都是官方支持的,不过也存在其他构建类型。
2 ROS 2 包由什么组成?
Section titled “2 ROS 2 包由什么组成?”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
my_package/ CMakeLists.txt include/my_package/ package.xml src/Python
my_package/ package.xml resource/my_package setup.cfg setup.py my_package/3 工作空间中的包
Section titled “3 工作空间中的包”一个工作空间可以包含任意数量的包,每个包都在自己的文件夹中。你还可以在一个工作空间中拥有不同构建类型的包(CMake、Python 等)。但不能有嵌套的包。
最佳实践是在工作空间内使用一个 src 文件夹,并在其中创建你的包。这样可以保持工作空间顶层”干净”。
一个简单的工作空间可能如下所示:
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
$ cd ~/ros2_ws/srcmacOS
$ cd ~/ros2_ws/srcWindows
$ cd \ros2_ws\src在 ROS 2 中创建新包的命令语法为:
CMake
$ ros2 pkg create --build-type ament_cmake --license Apache-2.0 <package_name>Python
$ ros2 pkg create --build-type ament_python --license Apache-2.0 <package_name>在本教程中,你将使用可选参数 --node-name 和 --license。--node-name 选项会在包中创建一个简单的 Hello World 类型可执行文件,--license 声明包的许可证信息。
在终端中输入以下命令:
CMake
$ ros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name my_node my_packagePython
$ ros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_node my_package现在你的工作空间的 src 目录中将有一个名为 my_package 的新文件夹。
运行命令后,你的终端将返回以下消息:
CMake
going to create a new packagepackage name: my_packagedestination directory: /home/user/ros2_ws/srcpackage format: 3version: 0.0.0description: TODO: Package descriptionmaintainer: ['<name> <email>']licenses: ['Apache-2.0']build type: ament_cmakedependencies: []node_name: my_nodecreating folder ./my_packagecreating ./my_package/package.xmlcreating source and include foldercreating folder ./my_package/srccreating folder ./my_package/include/my_packagecreating ./my_package/CMakeLists.txtcreating ./my_package/src/my_node.cppPython
going to create a new packagepackage name: my_packagedestination directory: /home/user/ros2_ws/srcpackage format: 3version: 0.0.0description: TODO: Package descriptionmaintainer: ['<name> <email>']licenses: ['Apache-2.0']build type: ament_pythondependencies: []node_name: my_nodecreating folder ./my_packagecreating ./my_package/package.xmlcreating source foldercreating folder ./my_package/my_packagecreating ./my_package/setup.pycreating ./my_package/setup.cfgcreating folder ./my_package/resourcecreating ./my_package/resource/my_packagecreating ./my_package/my_package/__init__.pycreating folder ./my_package/testcreating ./my_package/test/test_copyright.pycreating ./my_package/test/test_flake8.pycreating ./my_package/test/test_pep257.pycreating ./my_package/my_package/my_node.py你可以看到新包自动生成的文件。
将包放在工作空间中的好处在于,你可以在工作空间根目录运行 colcon build 一次性构建多个包,而不必逐个构建。
返回到你的工作空间根目录:
Linux
$ cd ~/ros2_wsmacOS
$ cd ~/ros2_wsWindows
$ cd \ros2_ws现在你可以构建你的包了:
Linux
$ colcon buildmacOS
$ colcon buildWindows
$ colcon build --merge-installWindows 对路径长度有限制,因此 merge-install 会将所有路径合并到 install 目录中。
回想一下上一个教程,你的 ros2_ws 中还有 ros_tutorials 包。你可能已经注意到运行 colcon build 也构建了 turtlesim 包。当你的工作空间中只有少量包时这没问题,但当有很多包时,colcon build 可能需要很长时间。
要仅构建 my_package 包,你可以运行:
$ colcon build --packages-select my_package3 Source setup 文件
Section titled “3 Source setup 文件”要使用你的新包和可执行文件,首先打开一个新终端并 source 你的主 ROS 2 安装环境。
然后,在 ros2_ws 目录中运行以下命令来 source 你的工作空间:
Linux
$ source install/local_setup.bashmacOS
$ . install/local_setup.bashWindows
$ call install/local_setup.bat现在你的工作空间已添加到路径中,你将能够使用新包的可执行文件。
要运行你在创建包时使用 --node-name 参数创建的可执行文件,输入以下命令:
$ ros2 run my_package my_node它将在你的终端返回一条消息:
CMake
hello world my_package packagePython
Hi from my_package.5 查看包内容
Section titled “5 查看包内容”在 ros2_ws/src/my_package 中,你将看到 ros2 pkg create 自动生成的文件和文件夹:
CMake
CMakeLists.txt include package.xml srcmy_node.cpp 位于 src 目录中。这是你将来放置所有自定义 C++ 节点的地方。
Python
my_package package.xml resource setup.cfg setup.py testmy_node.py 位于 my_package 目录中。这是你将来放置所有自定义 Python 节点的地方。
6 自定义 package.xml
Section titled “6 自定义 package.xml”你可能已经注意到,创建包后的返回消息中 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 来编写。