3、ROS2——包Package

📅 2026/8/24 15:04:54
3、ROS2——包Package
一、简介ROS2 的软件工程以包Package为基本组织单元理解包的结构、依赖管理和构建方式是开发和维护 ROS2 系统的基础。包是 ROS2 中组织代码、资源、配置和接口定义的最小分发单元。从技术上说任何包含package.xml文件的目录都可以视为一个 ROS2 包。这个文件是包的“身份证”记录了包的元信息名称、版本、维护者、许可证等和依赖关系。一个包通常包含源代码C 或 Python自定义消息、服务、动作定义msg/、srv/、action/配置文件config/、params/启动文件launch/资源文件URDF、RViz、world 等测试代码文档包不直接参与运行时通信而是通过编译生成可执行文件节点或库再在运行时实例化为节点。那为什么需要包呢1、模块化将不同功能分离便于独立开发、测试和复用。2、依赖管理通过package.xml显式声明依赖构建系统可自动解析和排序。3、分发与安装包是 ROS2 软件发布的最小单位可通过 apt、源码或二进制方式分发。4、索引与发现安装后的包通过ament 索引被ros2 pkg list等工具发现。5、工程规范统一的项目结构让团队协作和大规模项目维护更加容易。二、如何创建一个包创建一个包我们一般说创建一个Cpp包或者创建一个Python包但是事实上包不严格只有这两种包的分类在之后会介绍到那我们如何创建一个包呢在ros2中有专门用于创建包的命令最基础的命令格式如下通常需要在你的工作空间workspace的src目录下执行ros2 pkg create 你的包名 --build-type 构建类型 --license 许可证你的包名为你即将创建的功能包命名。--build-type指定构建类型这是必须的。主要选择有ament_cmake用于C包。ament_python用于Python包。--license指定许可证例如Apache-2.0这是创建包时的推荐做法常用选项参数你可以通过添加以下选项来丰富你的包模板--dependencies声明此包的依赖项多个依赖用空格分隔。这能自动帮你把依赖信息添加到package.xml和CMakeLists.txt文件中。--node-name创建一个与包同名的、简单的可执行节点C为.cppPython为.py。--description为你的包添加描述信息。--maintainer-name和--maintainer-email设置维护者信息。--destination-directory指定创建包的目录默认为当前目录。下边打开工作空间创建一个最简单的cpp和Python包。创建Python包ros2 pkg create my_py_pkg --build-type ament_python --dependencies rclpy --license Apache-2.0创建cpp包ros2 pkg create my_cpp_pkg --build-type ament_cmake --dependencies rclcpp --license Apache-2.0这样我们就创建好了两个最基本的包可以用colcon build进行编译注意一定不要在src文件夹下进行编译一定要在工作空间进行编译切记切记这样我们就得到了两个最基本的包。三、包的分类ROS2 包根据构建类型主要分为构建类型说明ament_cmake基于 CMake 的 C/C 包ament_python基于 setuptools 的 Python 包ament_cmake_python混合 C 与 Python 的包rosidl_generate_interfaces消息/服务/动作接口包metapackage元包仅聚合其他包ament_mypy等特殊工具包四、包的结构C包的结构一般为my_pkg/ ├── CMakeLists.txt ├── package.xml ├── include/ │ └── my_pkg/ │ ├── my_node.hpp │ └── ... ├── src/ │ ├── talker.cpp │ ├── listener.cpp │ └── ... ├── launch/ │ └── demo.launch.py ├── config/ │ └── params.yaml └── test/Python包的结构一般为my_py_pkg/ ├── package.xml ├── setup.py ├── setup.cfg ├── resource/ │ └── my_py_pkg # 空标记文件用于 ament 索引 ├── my_py_pkg/ │ ├── __init__.py │ ├── talker.py │ ├── listener.py │ └── ... ├── launch/ ├── config/ └── test/4.1 package.xml首先解释一下两种包都具有的一个文件就是package.xml package.xml是包的核心描述文件。?xml version1.0? ?xml-model hrefhttp://download.ros.org/schema/package_format3.xsd schematypenshttp://www.w3.org/2001/XMLSchema? package format3 namemy_pkg/name version0.1.0/version descriptionMy ROS2 package/description maintainer emailuserexample.comUser/maintainer licenseApache-2.0/license !-- 构建工具依赖 -- buildtool_dependament_cmake/buildtool_depend !-- 通用依赖构建、导出、运行都依赖 -- dependrclcpp/depend dependstd_msgs/depend dependsensor_msgs/depend !-- 仅编译期依赖 -- !-- build_depend.../build_depend -- !-- 仅导出依赖 -- !-- build_export_depend.../build_export_depend -- !-- 仅运行期依赖 -- !-- exec_depend.../exec_depend -- !-- 测试依赖 -- test_dependament_lint_auto/test_depend test_dependament_lint_common/test_depend export build_typeament_cmake/build_type /export /package标签含义depend等价于同时声明build_depend、build_export_depend、exec_depend最常用build_depend编译时需要build_export_depend其他包依赖本包导出头文件/库时需要exec_depend运行时需要test_depend仅测试时需要buildtool_depend构建工具依赖如ament_cmake、ament_pythonbuildtool_export_depend导出构建工具依赖doc_depend文档构建依赖对于 Python 包build_type应写为ament_pythonexport build_typeament_python/build_type /export4.2ament_cmake包的CMakeLists.txtcmake_minimum_required(VERSION 3.8) project(my_pkg) # 设置 C 标准 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) endif() # 必须找到 ament_cmake find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) # 增加可执行文件 add_executable(talker src/talker.cpp) add_executable(listener src/listener.cpp) # 包含头文件目录 target_include_directories(talker PRIVATE include) target_include_directories(listener PRIVATE include) # 自动链接依赖库、头文件和定义 ament_target_dependencies(talker rclcpp std_msgs) ament_target_dependencies(listener rclcpp std_msgs) # 安装可执行文件到 lib/${PROJECT_NAME} install(TARGETS talker listener DESTINATION lib/${PROJECT_NAME}) # 安装 launch 和 config 目录到 share/${PROJECT_NAME} install(DIRECTORY launch config DESTINATION share/${PROJECT_NAME}) # 如果本包提供库给下游使用导出依赖 ament_export_include_directories(include) ament_export_dependencies(rclcpp std_msgs) # 必须放在最后 ament_package()要点find_package(ament_cmake REQUIRED)是必须的。ament_target_dependencies可以自动处理头文件路径、链接库、编译定义等。可执行文件安装到install/lib/${PROJECT_NAME}/。ament_package()必须放在文件末尾。基础设置声明CMake最低版本和项目包名称。包名必须与package.xml中的一致。cmake_minimum_required(VERSION 3.8) # 推荐3.8 project(my_cpp_pkg)查找依赖使用find_package查找所有依赖包无论是ROS 2的还是系统的。find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED)声明可执行文件或库可执行文件用add_executable指定源文件。库用add_library指定源文件。链接依赖使用ament_target_dependencies为目标可执行文件或库链接依赖。add_executable(talker src/talker.cpp) ament_target_dependencies(talker rclcpp std_msgs)安装规则使用install命令指定将编译好的可执行文件、库、头文件、launch文件等安装到何处。这对于ros2 run找到它们是必需的。install(TARGETS talker DESTINATION lib/${PROJECT_NAME}) install(DIRECTORY launch/ DESTINATION share/${PROJECT_NAME}/launch)完成构建以ament_package()结尾用于生成与ROS 2工具链相关的配置4.3ament_python包的setup.py与setup.cfgfrom setuptools import setup, find_packages package_name my_py_pkg setup( namepackage_name, version0.0.0, packagesfind_packages(exclude[test]), data_files[ # 在 ament 索引中注册包 (share/ament_index/resource_index/packages, [resource/ package_name]), # 安装 package.xml 到 share/${package_name} (share/ package_name, [package.xml]), ], install_requires[setuptools], zip_safeTrue, maintainerUser, maintainer_emailuserexample.com, descriptionMy ROS2 Python package, licenseApache-2.0, tests_require[pytest], entry_points{ console_scripts: [ # 可执行命令 包名.模块名:main函数 talker my_py_pkg.talker:main, listener my_py_pkg.listener:main, ], }, )关键点entry_points中的console_scripts会在install/lib/my_py_pkg/下创建可执行脚本。resource/my_py_pkg是一个空文件用于在 ament 索引中注册包ros2 pkg list才能发现它。