@[toc]
参考官方文档:Creating a package
ROS 2软件包概念简介
1. ROS 2软件包是什么?
一个包可以被认为是你的 ROS 2 代码的容器。 如果您希望能够安装您的代码或与他人共享,那么您需要将其组织在一个包中。 借助软件包,您可以发布您的 ROS 2 作品并允许其他人轻松构建和使用它。 ROS 2 中的包创建使用 ament 作为其构建系统,并使用 colcon 作为其构建工具。 您可以使用官方支持的 CMake 或 Python 创建包,但确实存在其他构建类型。
2. ROS 2软件包是如何构成的?
ROS 2 Python 和 CMake 包都有自己的最低要求内容:
CMake
- package.xml:包含关于软件包的元信息的文件
- CMakeLists.txt:描述了如何在包内构建代码的文件
最简单的包可能有一个看起来像这样的文件结构:
my_package/
CMakeLists.txt
package.xml
Python
- package.xml:包含关于软件包的元信息的文件
- setup.py:包含如何安装软件包的说明
- setup.cfg:当软件包有可执行文件时,需要setup.cfg,以便ros2 run能找到它们
- /<package_name>:一个与你的软件包同名的目录,被ROS 2工具用来寻找你的软件包,包含__init__.py
最简单的包可能有一个看起来像这样的文件结构:
my_package/
setup.py
package.xml
resource/my_package
3. 工作空间中的包
一个工作区可以包含任意数量的包,每个包都在自己的文件夹中。 您还可以在一个工作区(CMake、Python 等)中包含不同构建类型的包。 你不能有嵌套的包。 最佳做法是在您的工作区中有一个 src 文件夹,并在其中创建您的包。 这使工作区的顶层保持“干净”。 一个普通的工作区可能看起来像:
workspace_folder/
src/
package_1/
CMakeLists.txt
package.xml
package_2/
setup.py
package.xml
resource/package_2
...
package_n/
CMakeLists.txt
package.xml
1. 创建一个包
进入到在前面的教程中创建的ros_ws文件夹中:
cd ~/ros2_ws/src
在ROS 2中,创建一个新包的命令语法是:
CMake:
ros2 pkg create --build-type ament_cmake <package_name>
Python:
ros2 pkg create --build-type ament_python <package_name>
对于本教程,您将使用可选参数 --node-name 来在包中创建一个简单的 Hello World 类型可执行文件。 在您的终端中输入以下命令:
CMake:
ros2 pkg create --build-type ament_cmake --node-name my_node my_package
Python:
ros2 pkg create --build-type ament_python --node-name my_node my_package
现在你将在工作区的src目录下有一个新的文件夹,名为my_package。
运行该命令后,你的终端将返回以下信息:
CMake:
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: ['TODO: License declaration']
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:
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: ['TODO: License declaration']
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
你可以看到自动生成的新软件包的文件。
2. 构建软件包
将包放在工作区中特别有价值,因为您可以通过在工作区根目录中运行 colcon build 来一次构建许多包。 否则,您将不得不单独构建每个包。 返回到工作区的根目录:
cd ~/ros2_ws
然后构建软件包:
colcon build
回想一下上一个教程,您的 ros2_ws 中也有 ros_tutorials 包。 您可能已经注意到运行 colcon build 也会构建 turtlesim 包。 当您的工作区中只有几个包时这很好,但是当有很多包时,colcon 构建可能需要很长时间。 下次只构建 my_package 包,你可以运行:
colcon build --packages-select my_package
3. source设置文件
要使用你的新包和可执行文件,首先打开一个新的终端,并source你的ROS 2主安装。
source /opt/ros/humble/setup.bash
然后,在ros2_ws目录下,运行下面的命令,source你的工作空间:
. install/local_setup.bash
现在,你的工作空间已经被添加到你的路径(path)中,你将能够使用你的新包的可执行文件。
4. 使用包
要运行你在创建软件包时使用 --node-name 参数创建的可执行文件,请输入以下命令:
ros2 run my_package my_node
终端返回信息如下:
CMake:
hello world my_package package
Python:
Hi from my_package.
5. 检查软件包内容
在 ros2_ws/src/my_package 里面,你会看到 ros2 pkg 自动生成的文件和文件夹:
CMake:
CMakeLists.txt include package.xml src
my_node.cpp在src目录里面。这是你将来所有自定义C++节点的地方。
Python:
my_package package.xml resource setup.cfg setup.py test
my_node.py在my_package目录里面。这是你将来所有自定义Python节点的地方。
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(Apache License 2.0):
<license>Apache License 2.0</license>
完成编辑后,不要忘记保存。
在许可证标签下方,您会看到一些以 _depend 结尾的标签名称。 这是你的 package.xml 将列出它对其他包的依赖关系的地方,供 colcon 搜索。 my_package 很简单,没有任何依赖关系,但您会在接下来的教程中看到这个空间的使用。
Python:
setup.py文件包含与package.xml相同的描述、维护者和许可字段,所以你也需要设置这些字段。它们需要在两个文件中完全匹配。版本和名称(package_name)也需要完全匹配,并且应该在两个文件中自动填充。
from setuptools import setup
package_name = 'my_py_pkg'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
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',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'my_node = my_py_pkg.my_node:main'
],
},
)
编辑维护者(maintainer)、维护者邮件(maintainer_email)和描述行(description),使之与package.xml匹配。