欢迎光临
我们一直在努力

ROS文件解读(package .xml--CMakeLists.txt)

ROS Package(功能包)

  • ROS Package 是 ROS 中最小的可编译 / 可运行单元,一个机器人功能(比如激光 SLAM、电机控制)通常对应一个或多个 Package。
  • 每个 Package 必须包含 package.xml(描述包的元信息)和 CMakeLists.txt(编译构建规则),缺少任何一个都不被 ROS 识别为合法 Package。

ROS中的依赖和CMake库

ROS 里的 “依赖” 本质是:你的功能包想要正常编译、运行,必须依赖的其他软件 / 代码 / 库资源。就像你做一道菜需要食材,你的 ROS 包实现功能也需要 “食材”—— 这些 “食材” 就是依赖。

依赖的分类(对应 package.xml 里的标签)

依赖类型通俗解释例子
编译时依赖 编译代码(catkin_make)时必须有的 “食材”(比如头文件、编译规则) roscpp(提供 C++ 的头文件)、message_generation(生成 msg 代码)
运行时依赖 运行 ROS 节点(rosrun)时必须有的 “食材”(比如动态链接库、可执行程序) roscpp(提供运行节点的库文件)、rviz(运行可视化工具)
测试时依赖 运行 ROS 测试(rostest)时需要的 “食材” rostest、gtest
  • 头文件(.h/.hpp):比如#include <ros/ros.h> 中的ros.h就是roscpp包提供的头文件,没有它编译代码会报错 “找不到头文件”。
  • 库文件(.so/.a):Linux 下的动态 / 静态链接库,比如roscpp会生成libroscpp.so,运行节点时系统需要找到这个库才能启动。
  • 可执行程序:比如依赖rviz,本质是依赖rviz包编译出的rviz可执行文件。
  • msg/srv 定义文件:比如依赖std_msgs,是依赖它定义的String.msg、Int32.msg等消息格式。
    举个直观例子

    你写了一个 C++ ROS 节点,代码第一行是:

    #include <ros/ros.h> // 用到roscpp的头文件

    编译时,编译器需要找到ros.h这个文件(来自roscpp包)—— 这是编译时依赖;运行时,你的节点需要调用roscpp的动态库libroscpp.so—— 这是运行时依赖;如果缺少这两个依赖,要么编译失败,要么运行时提示 “找不到库”。

    CMake 库不是 ROS 特有的,是 CMake 构建系统中的核心概念,ROS 基于 CMake 扩展了 catkin,所以会用到这个概念。

    1. 先理解 “库(Library)” 的基础

    编程中的 “库” 是提前编译好的、可复用的代码集合(对比:可执行文件是直接运行的程序,库是被程序调用的代码)。比如你写的 ROS 节点(可执行文件)会调用roscpp的库,不用自己重新写 “创建节点、发布话题” 的代码。

    2. CMake 库的具体含义

    在 CMake 中,“CMake 库” 是指:CMake 通过特定指令(如find_package、target_link_libraries)识别、管理、链接的 “库文件”(.so/.a)或 “库配置”。简单说:CMake 库是 CMake 能 “认得到”、能帮你链接到代码里的库资源。

    3. CMake 库的核心作用(ROS 场景下)

    在 ROS 的CMakeLists.txt中,你写:

    # 1. 查找roscpp这个CMake库(本质是找roscpp的编译配置和库文件)
    find_package(catkin REQUIRED COMPONENTS roscpp)

    # 2. 将roscpp的CMake库链接到你的节点
    target_link_libraries(my_node ${catkin_LIBRARIES})

    这两行的核心是:

  • find_package(roscpp):CMake 会去系统中找roscpp的 “库配置文件”(比如roscppConfig.cmake),这个文件告诉 CMake:
    • roscpp的头文件在哪(比如/opt/ros/noetic/include);
    • roscpp的库文件在哪(比如/opt/ros/noetic/lib/libroscpp.so);
  • ${catkin_LIBRARIES}:是 CMake 变量,包含了所有找到的 ROS 库(如roscpp、std_msgs)的库文件路径,target_link_libraries会把这些库 “链接” 到你的可执行文件中,让你的节点能调用库的功能。

新手入门时,不用深究 CMake 库的底层实现,只需记住:在 CMakeLists.txt 中,find_package填你依赖的 ROS 包名,target_link_libraries加上${catkin_LIBRARIES},就能正确链接依赖的 CMake 库。

package.xml 解读

package.xml 是包的 “身份证”,用于描述包的元信息(名称、版本、依赖、作者等),ROS 通过它识别包的基本信息和依赖关系。

核心结构(以 ROS Noetic/Melodic 为例,ROS2 格式略有差异)

<?xml version="1.0"?>
<!– 声明ROS版本,noetic对应格式2,kinetic/melodic也常用2 –>
<package format="2">
<!– 1. 必选基础信息 –>
<name>my_package</name> <!– 包名(唯一,小写+下划线) –>
<version>1.0.0</version> <!– 版本号(语义化:主版本.次版本.修订号) –>
<description>My first ROS package</description> <!– 功能描述 –>
<maintainer email="your@email.com">Your Name</maintainer> <!– 维护者(必填) –>
<license>Apache-2.0</license> <!– 许可证(如MIT、BSD、GPL) –>

<!– 2. 依赖声明(核心) –>
<!– build_depend:编译时依赖(比如头文件、CMake库) –>
<build_depend>roscpp</build_depend>
<!– exec_depend:运行时依赖(比如ROS节点运行需要的库) –>
<exec_depend>roscpp</exec_depend>
<!– build_export_depend:编译导出依赖(其他包依赖本包时需要的编译依赖) –>
<build_export_depend>roscpp</build_export_depend>
<!– test_depend:测试时依赖 –>
<test_depend>rostest</test_depend>

<!– 3. 可选信息 –>
<author>Your Name</author> <!– 作者 –>
<url type="website">https://your-url.com</url> <!– 文档/代码地址 –>
</package>

标签作用
<name> 包的唯一标识,命名规则:小写字母 + 下划线(如lidar_driver)
<build_depend> 编译本包需要的依赖(比如roscpp、std_msgs)
<exec_depend> 运行本包节点需要的依赖(大部分场景和build_depend重复)
<maintainer> 必须填写,否则catkin_make会报错,格式:姓名 + 邮箱

在 Package 目录下执行:

catkin_lint . # 检查package.xml语法是否正确
rospkg info my_package # 查看包的元信息(验证是否识别)

以下是一段package.xml,读者可以自行解读,

<?xml version="1.0"?>
<package format="2">
<name>imu_filter</name>
<version>0.0.0</version>
<description>imu_filter</description>
<maintainer email="a@a.com">a</maintainer>
<license>BSD</license>

<buildtool_depend>catkin</buildtool_depend>

<build_depend>roscpp</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>tf</build_depend>
<build_depend>tf2</build_depend>
<build_depend>dynamic_reconfigure</build_depend>

<exec_depend>roscpp</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>tf</exec_depend>
<exec_depend>tf2</exec_depend>
<exec_depend>dynamic_reconfigure</exec_depend>
</package>

CMakeLists.txt 解读

CMakeLists.txt 是编译规则文件,告诉 ROS(实际是 catkin 构建系统)如何编译代码、链接库、安装文件等。ROS 基于 CMake 扩展了 catkin,所以文件里既有 CMake 原生语法,也有 catkin 特有语法。

# 1. 声明CMake最低版本(ROS Noetic对应3.0.2+)
cmake_minimum_required(VERSION 3.0.2)

# 2. 声明包名(必须和package.xml的<name>一致)
project(my_package)

# 3. 设置编译选项(可选,解决中文编码、C++版本等问题)
add_compile_options(-std=c++11) # 指定C++11标准

# 4. 查找依赖的ROS包(核心)
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_generation # 如果自定义msg/srv,需要加这个
)

# 5. 声明catkin包的导出信息(固定模板)
catkin_package(
INCLUDE_DIRS include # 头文件目录
LIBRARIES ${PROJECT_NAME} # 编译生成的库名
CATKIN_DEPENDS roscpp std_msgs # 依赖的ROS包
# DEPENDS system_lib # 如果依赖非ROS库(如Eigen),加这里
)

# 6. 包含头文件目录(让编译器找到头文件)
include_directories(
include
${catkin_INCLUDE_DIRS} # ROS依赖包的头文件目录
)

# 7. 编译可执行文件(核心:生成ROS节点)
add_executable(my_node src/my_node.cpp) # 源文件→可执行文件
# 链接库(必须加,否则编译报错)
target_link_libraries(my_node
${catkin_LIBRARIES}
)

# 8. 安装(可选:将可执行文件安装到ROS环境)
install(TARGETS my_node
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
# 安装头文件(可选)
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
)

以下是一段CMakeLists.txt ,读者可以自行解读,

cmake_minimum_required(VERSION 2.8.3)
project(imu_filter)

# 1. 查找所有依赖(顺序固定)
find_package(catkin REQUIRED COMPONENTS
roscpp
sensor_msgs
geometry_msgs
tf
tf2
dynamic_reconfigure
)

# 2. 生成动态参数头文件(仅针对需要的两个滤波器)
generate_dynamic_reconfigure_options(
cfg/MyStuff.cfg
cfg/MyStuff2.cfg
)

# 3. Catkin 包导出配置(顺序固定)
catkin_package(
CATKIN_DEPENDS roscpp sensor_msgs geometry_msgs tf tf2 dynamic_reconfigure
)

# 4. 头文件包含路径(顺序固定)
include_directories(
${catkin_INCLUDE_DIRS}
)

# 5. 第一步:创建可执行目标(严格按「先创建,后操作」)
add_executable(madgwick_imu_filter src/Madgwick_filter.cpp)
add_executable(mahony_imu_filter src/Mahony_filter.cpp)
add_executable(bias_calculator src/bias_calculator.cpp)

# 6. 第二步:添加依赖(仅给需要动态参数的两个目标加)
add_dependencies(madgwick_imu_filter ${PROJECT_NAME}_gencfg ${catkin_EXPORTED_TARGETS})
add_dependencies(mahony_imu_filter ${PROJECT_NAME}_gencfg ${catkin_EXPORTED_TARGETS})
# bias_calculator 无动态参数,无需添加此依赖

# 7. 第三步:链接库(所有目标都需要,顺序在创建和依赖之后)
target_link_libraries(madgwick_imu_filter ${catkin_LIBRARIES})
target_link_libraries(mahony_imu_filter ${catkin_LIBRARIES})
target_link_libraries(bias_calculator ${catkin_LIBRARIES})

指令作用
project(my_package) 声明包名,必须和package.xml的<name>完全一致
find_package() 查找依赖的 ROS 包,比如roscpp(C++ 接口)、rospy(Python 接口)
catkin_package() 声明本包的导出信息,供其他依赖本包的包使用
add_executable() 将.cpp源文件编译成可执行文件(ROS 节点)
target_link_libraries() 链接依赖库(ROS 的核心库都在${catkin_LIBRARIES}里)

注意:

add_executable() 将.cpp源文件编译成可执行文件(ROS 节点)
常见扩展场景
  • 编译多个节点

    # 编译第一个节点
    add_executable(node1 src/node1.cpp)
    target_link_libraries(node1 ${catkin_LIBRARIES})
    # 编译第二个节点
    add_executable(node2 src/node2.cpp)
    target_link_libraries(node2 ${catkin_LIBRARIES})

    自定义 msg/srv 文件:需要在find_package后添加:

    add_message_files(FILES MyMsg.msg) # 自定义msg文件
    add_service_files(FILES MySrv.srv) # 自定义srv文件
    generate_messages(DEPENDENCIES std_msgs) # 生成msg/srv的代码

    在 ROS 工作空间(catkin_ws)根目录执行:

    catkin_make # 编译所有包
    # 或指定编译当前包
    catkin_make –cmake-args -DCMAKE_BUILD_TYPE=Release –pkg my_package

    两个文件的关联

  • package.xml 中声明的依赖(如roscpp),必须在CMakeLists.txt的find_package中对应包含,否则编译会找不到依赖。
  • CMakeLists.txt的project名称必须和package.xml的<name>完全一致,否则 ROS 无法识别包。
  • 新增依赖时,两个文件都要修改:先在package.xml加<build_depend>/<exec_depend>,再在CMakeLists.txt加find_package。

总结

  • package.xml 是元信息文件,核心作用是声明包名、版本、依赖,让 ROS 识别包的基本信息。
  • CMakeLists.txt 是编译规则文件,核心作用是指定编译源文件、链接依赖库、生成可执行文件(ROS 节点)。
  • 两个文件是 ROS 功能包的 “标配”,且依赖声明、包名必须保持一致,否则会导致编译 / 运行错误。
  • 赞(0)
    未经允许不得转载:171主机测评 » ROS文件解读(package .xml--CMakeLists.txt)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址