知识分享 ros ROS1&2之CmakeList.txt与package.xml MGodmonkey 2023-07-26 2024-01-30 1. CMakeLists.txt与package.xml的作用
在ROS 系统的功能包中 要包含 CMakeLists.txt 与 package.xml 文件来编译功能包的内容
CMakeLists.txt 原本是Cmake 编译系统的规则文件,而Catkin 编译系统基本沿用了CMake 的编译风格,只是针对ROS 工程添加了一些宏定义。所以在写法上,catkin 的 CMakeLists.txt 与CMake 的基本一致。用cmake 命令创建功能包 时,会自动生成CMakeList.txt 文件,已配置了多数编译选项,且包含详细的注释,只需稍作修改便可编译自己的文件。
而package.xml 文件是描述功能包清单的文件,包括功能包的名称 、版本号 、作者信息 、许可信息 、编译依赖 和运行依赖 等。
所以 CMakeLists.txt 非常重要,它指定了由源码到目标文件的规则,catkin 编译系统在工作时首先会找到每个package 下的 CMakeLists.txt ,然后按照规则来编译构建
2. 生成CMakeLists.txt
2.1 ROS1
ROS1 可通过用catkin_create_pkg 命令创建功能包 ,这会自动生成CMakeLists.txt 和package.xml 文件的。
1 2 3 4 5 6 7 8 9 10 mkdir -p ~/catkin_ws/srccd ~/catkin_ws/srccatkin_create_pkg test std_msgs rospy roscpp tree
通过上面的命令生成的工作空间 如下
include
:存放**.h**的头文件
src
:可同时存放**.cpp或 .py的源文件,但一般 .py**文件存放在scripts
目录中
scripts
:习惯存放**.py的 python**文件,需要自己创建
注:python代码和c++代码不分家,可同时存放在同一功能包中
2.2 ROS2
ROS2 可通过如下的命令来创建功能包 以及必要的CMakeList.txt 和package.xml 文件
1 2 3 4 5 6 7 8 9 10 11 mkdir -p ~/dev_ws/srccd ~/dev_ws/srcros2 pkg create --build-type ament_cmake test_c ros2 pkg create --build-type ament_python test_python tree
通过以上命令生成的工作空间如下:
test_c/include
:存放**.h**的头文件
test_c/src
:存放**.cpp的 C++**源文件
test_python/test_python
:存放**.py的 python**文件
注:与ROS1不同,同一功能包内只能同时包含python文件或者C++文件中的一种
3. CMakeLists.txt编写
3.1 ROS1
常用的ROS1 中CMakeLists.txt 架构如下
视频解析参考:中科院软件所-机器人操作系统入门(ROS入门教程)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 cmake_minimum_required () project () find_package () catkin_python_setup() add_message_files() add_service_files() add_action_files() generate_message() catkin_package() add_library () add_executable () add_dependencies () target_link_libraries () catkin_add_gtest() install ()
需要自己配置的项目一般就下面几种:
CMakeLists.txt模板参考:CMakeLists.txt
更多教程参考:catkin/CMakeLists.txt - ROS Wiki
3.2 ROS2
常用的ROS2 中CMakeLists.txt 架构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cmake_minimum_required () project () find_package () ament_target_dependencies() add_executable () install () ament_package() rosidl_generate_interfaces()
示例模板如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 cmake_minimum_required (VERSION 3.5 )project (test_c)if (NOT CMAKE_C_STANDARD) set (CMAKE_C_STANDARD 99 ) endif ()if (NOT CMAKE_CXX_STANDARD) set (CMAKE_CXX_STANDARD 14 ) endif ()if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) add_compile_options (-Wall -Wextra -Wpedantic) endif ()find_package (ament_cmake REQUIRED)find_package (rclcpp REQUIRED)find_package (std_msgs REQUIRED)add_executable (talker src/publisher_member_function.cpp) ament_target_dependencies(talker rclcpp std_msgs) install (TARGETS talker DESTINATION lib/${PROJECT_NAME} ) if (BUILD_TESTING) find_package (ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() endif ()find_package (geometry_msgs REQUIRED)find_package (rosidl_default_generators REQUIRED)rosidl_generate_interfaces(${PROJECT_NAME} "msg/Num.msg" "msg/Sphere.msg" "srv/AddThreeInts.srv" DEPENDENCIES geometry_msgs ) ament_package()
相较于基于catkin 的CMake 文件,基于ament 的明显简洁很多
假设你编写了~/dev_ws/src/test.cpp
文件后,需要修改的步骤如下:
链接源代码
1 2 add_executable (test src/test .cpp) ament_target_dependencies(test rclcpp)
添加下面这两行代码的目的是让编译器编译~/dev_ws/src/test_c/test.cpp
这个文件
1 2 3 4 install (TARGETS test DESTINATION lib/${PROJECT_NAME} )
当你自定义消息类型时还需要消息类型文件
1 2 3 4 5 6 7 8 9 10 11 find_package (geometry_msgs REQUIRED)find_package (rosidl_default_generators REQUIRED)rosidl_generate_interfaces(${PROJECT_NAME} "msg/Num.msg" "msg/Sphere.msg" "srv/AddThreeInts.srv" DEPENDENCIES geometry_msgs )
4. package.xml编写
package.xml 的框架如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <package format ="3" > <name > ..</name > <version > 0.0.0</version > <description > ...</description > <maintainer email ="lanhanba@todo.todo" > ...</maintainer > <license > ...</license > <buildtool_depend > ...</buildtool_depend > <exec_depend > ...</exec_depend > <exec_depend > ...</exec_depend > <export > <build_type > ...</build_type > </export > </package >
相较于CMakeList.txt ,package.xml 的语法就简单许多,且ROS1 和ROS2 的标签语法通用
<build_depend></build_depend> : 标签定义了功能包中代码编译时所依赖的其他功能包
<exec_depend><exec_depend> : 标签定义了功能包中可执行程序运行时所依赖的其他功能包
自定义数据类型 :话题消息msg 、服务数据srv 、动作数据action
模板如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?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 > test_c</name > <version > 0.0.0</version > <description > TODO: Package description</description > <maintainer email ="lanhanba@todo.todo" > lanhanba</maintainer > <license > TODO: License declaration</license > <buildtool_depend > catkin</buildtool_depend > <build_depend > roscpp</build_depend > <build_depend > rospy</build_depend > <build_depend > std_msgs</build_depend > <build_export_depend > roscpp</build_export_depend > <build_export_depend > rospy</build_export_depend > <build_export_depend > std_msgs</build_export_depend > <exec_depend > roscpp</exec_depend > <exec_depend > rospy</exec_depend > <exec_depend > std_msgs</exec_depend > <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 > <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 > <depend > rosidl_default_generators</depend > <depend > geometry_msgs</depend > <member_of_group > rosidl_interface_packages</member_of_group > </package >
5. 其他–Setup.py的修改
在ROS2-Python 功能包中,如果添加类似~/dev_ws/src/test_python/test.py
的python 文件,则需要对功能包中的Setup.py 进行如下的修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from setuptools import setuppackage_name = 'test_python' 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='lanhanba' , maintainer_email='lanhanba@todo.todo' , description='TODO: Package description' , license='TODO: License declaration' , tests_require=['pytest' ], entry_points={ 'console_scripts' : [ "test = test_python.test:main" , "test2 = test_python.test2:main" ], }, )
参考: