ROS1ROS2之CmakeList.txt和package.xml用法详解

前言:目前还在学习ROS+无人机框架中,,,
更多更新文章详见我的个人博客主页【前往】

文章目录

    • 1. CMakeLists.txt与package.xml的作用
    • 2. 生成CMakeLists.txt
      • 2.1 ROS1
      • 2.2 ROS2
    • 3. CMakeLists.txt编写
      • 3.1 ROS1
      • 3.2 ROS2
    • 4. package.xml编写
    • 5. 其他--Setup.py的修改

1. CMakeLists.txt与package.xml的作用

ROS系统的功能包中 要包含 CMakeLists.txtpackage.xml 文件来编译功能包的内容

CMakeLists.txt原本是Cmake编译系统的规则文件,而Catkin编译系统基本沿用了CMake的编译风格,只是针对ROS工程添加了一些宏定义。所以在写法上,catkinCMakeLists.txtCMake的基本一致。用cmake命令创建功能包时,会自动生成CMakeList.txt文件,已配置了多数编译选项,且包含详细的注释,只需稍作修改便可编译自己的文件。

package.xml文件是描述功能包清单的文件,包括功能包的名称版本号作者信息许可信息编译依赖运行依赖等。

所以 CMakeLists.txt 非常重要,它指定了由源码到目标文件的规则,catkin编译系统在工作时首先会找到每个package下的 CMakeLists.txt ,然后按照规则来编译构建

2. 生成CMakeLists.txt

2.1 ROS1

ROS1可通过用catkin_create_pkg命令创建功能包,这会自动生成CMakeLists.txtpackage.xml文件的。

# 创建工作空间
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src

# 注:std msgs rospy roscpp为创建功能时指定的铱赖,test为包名
# 也可以先不指定,后面在CMakeLists.txt和package.xmL中手动添加
catkin_create_pkg test std_msgs rospy roscpp

# 查看一下在~/catkin_ws/src目录下自动生成了哪些文件夹和文件
tree

通过上面的命令生成的工作空间如下

image-20230726150753757

include:存放**.h**的头文件

src:可同时存放**.cpp.py的源文件,但一般.py**文件存放在scripts目录中

scripts:习惯存放**.pypython**文件,需要自己创建

注:python代码和c++代码不分家,可同时存放在同一功能包中

2.2 ROS2

ROS2可通过如下的命令来创建功能包以及必要的CMakeList.txtpackage.xml文件

# 创建工作空间
mkdir -p ~/dev_ws/src
cd ~/dev_ws/src

# ament_cmake和ament_python分别代表c++和python两种代码的功能包
# test_c和test_python代表包名
ros2 pkg create --build-type ament_cmake test_c
ros2 pkg create --build-type ament_python test_python

# 查看一下在~/dev_ws/src目录下自动生成了哪些文件夹和文件
tree

通过以上命令生成的工作空间如下:

image-20230726151618480

  • test_c/include:存放**.h**的头文件

  • test_c/src:存放**.cppC++**源文件

  • test_python/test_python:存放**.pypython**文件

注:与ROS1不同,同一功能包内只能同时包含python文件或者C++文件中的一种

3. CMakeLists.txt编写

3.1 ROS1

  1. 常用的ROS1CMakeLists.txt架构如下

视频解析参考:中科院软件所-机器人操作系统入门(ROS入门教程)

cmake_minimum_required()	#CMake的最低版本号

project()					#项目名称

find_package()				#找到编译需要的其他CMake/Catkin	package 

catkin_python_setup()		#catkin新加宏,打开catkin的Python Module的支持

add_message_files()			#catkin新加宏,添加自定义Message文件 

add_service_files()         #catkin新加宏,添加自定义Service文件 

add_action_files()          #catkin新加宏,添加自定义Action文件 

generate_message()			#catkin新加宏,生成不同语言版本的msg/srv/action接口 

catkin_package()			#catkin新加宏,生成当前package的cmake配置,供依赖本包的其他软件包调用 

add_library()				#生成库 

add_executable()			#生成可执行二进制文件

add_dependencies()			#定义目标文件依赖于其他目标文件,确保其他目标已被构建 

target_link_libraries()		#链接

catkin_add_gtest()			#catkin新加宏,生成测试

install()					#生成可安装目标

需要自己配置的项目一般就下面几种:

  • include_directories

    • 用于设置头文件的相对路径
    • 全局路径默认为功能包所在目录,功能包的头文件一般放在功能包根目录下的include文件夹,
      所以需要此处添加此文件夹
    • 还包含catkin编译器默认的其他头文件路径,如:ROS默认安装路径、Linux系统路径等
  • add_exectuable

    • 用于设置需要编译的代码和可执行文件
    • 第一个参数为期望生成的可执行文件(节点)名称
    • 后面的参数为参与编译的源文件(.cpp),若需要多个代码文件,可依次列出,空格分隔
  • target_link_libraries

    • 用于设置链接库
    • 有些功需要使用系统或第三方库函数,通过该选项可以配置执行文件链接的库文件
    • 第一个参数与add_exectuable相同,为可执行文件(节点)名称
    • 后面的参数为需要链接的库,依次列出,空格分隔
  • add_dependencies

    • 用于设置依赖
    • 有时候需要自定义消息类型,消息类型会在编译过程中产生相应语言的代码。若编译的可执行文
      件依赖这些动态生成的代码,则需要添加${PROJECT NAME}generate messages_cpp配置
  • 自定义数据类型:消息msg、服务srv、动作action

    • find_package(catkin REQUIRE COMPONENTS message_generation)
    • catkin_package(CATKIN_DEPENDS message_runtime)
    • add_message_files(FILES xxx.msg)
    • add_service_files(FILES xxx.srv)
    • add_action_files(FILES xxx.action)
    • generate_messages(DEPENDENCIES std_msgs)

CMakeLists.txt模板参考:CMakeLists.txt

更多教程参考:catkin/CMakeLists.txt - ROS Wiki

3.2 ROS2

常用的ROS2CMakeLists.txt架构如下

cmake_minimum_required()			#CMake的最低版本号

project()				  		   #项目名称

find_package()   				    #查找系统中的依赖项

ament_target_dependencies()          #依赖于其他目标文件,确保其他目标已被构建 

add_executable()				    #生成可执行二进制文件

install()						   #生成可安装目标

ament_package()						#生成功能包

rosidl_generate_interfaces()		# 自定义消息类型接口

示例模板如下

cmake_minimum_required(VERSION 3.5)
project(test_c)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
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 dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)

add_executable(talker src/publisher_member_function.cpp)	# 修改2
ament_target_dependencies(talker rclcpp std_msgs)			# 修改3

install(TARGETS
  talker												# 修改4
  DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # uncomment the line when a copyright and license is not present in all source files
  #set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # uncomment the line when this package is not in a git repo
  #set(ament_cmake_cpplint_FOUND TRUE)
  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"				# 自定义1
  "msg/Sphere.msg"			# 自定义2
  "srv/AddThreeInts.srv"     # 自定义3
  DEPENDENCIES geometry_msgs
)

ament_package()

相较于基于catkinCMake文件,基于ament的明显简洁很多

假设你编写了~/dev_ws/src/test.cpp文件后,需要修改的步骤如下:

  1. 链接源代码
add_executable(test src/test.cpp)	# test为你输入节点后执行的名称,如ros2 run test_c test(前一个test_c为包名,后一个test则为这里的设置的名称,代表具体执行的代码)
ament_target_dependencies(test rclcpp)	# 添加依赖项
  1. 添加下面这两行代码的目的是让编译器编译~/dev_ws/src/test_c/test.cpp这个文件
install(TARGETS
  test
  DESTINATION lib/${PROJECT_NAME}
)

当你自定义消息类型时还需要消息类型文件

# 添加自定义消息类型需要添加项
# 下面两项是固定的,geometry_msgs是用于生成消息依赖包
find_package(geometry_msgs REQUIRED)
find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/Num.msg"				# 自定义1
  "msg/Sphere.msg"			# 自定义2
  "srv/AddThreeInts.srv"     # 自定义3
  DEPENDENCIES geometry_msgs
)

4. package.xml编写

package.xml的框架如下

<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.txtpackage.xml的语法就简单许多,且ROS1ROS2的标签语法通用

  • <build_depend></build_depend>: 标签定义了功能包中代码编译时所依赖的其他功能包
  • <exec_depend><exec_depend>: 标签定义了功能包中可执行程序运行时所依赖的其他功能包
  • 自定义数据类型:话题消息msg、服务数据srv、动作数据action

模板如下

<?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>

  <!-- ROS1 -->
  <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>
  
  <!-- ROS2_C++ -->
  <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>
    
  <!-- ROS2_python -->
  <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>
  
  <!-- ROS2中C++功能包添加自定义消息类型还需添加下面三行(固定形式,和上面的CMake修改搭配使用,python不需要) -->
  <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.pypython文件,则需要对功能包中的Setup.py进行如下的修改

from setuptools import setup

package_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': [
            # 结构如下:节点名 = 功能包名.代码文件.执行入口函数名(一般执行入口函数名都是main,也就是说python代码中一般要有main函数)
            # 通过ros2 run test_python test 来执行test_python.test:main下的函数
            # 如果有多个python代码文件都需要一一添加,名称不能一样
            "test = test_python.test:main",
            "test2 = test_python.test2:main"
        ],
    },
)

参考:

  • catkin/CMakeLists.txt - ROS Wiki

  • CMakeLists.txt - ROS Humble Wiki

  • 【ROS 学习笔记】CMakeLists.txt 与 package.xml - 知乎 (zhihu.com)

  • 详细分析一个ROS2 CMakeLists.txt文件_首飞爱玩机器人的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/46314.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu 20.04 Ubuntu18.04安装录屏软件Kazam

1.在Ubuntu Software里面输入Kazam&#xff0c;就可以找不到这个软件&#xff0c;直接点击install就可以了 2.使用方法&#xff1a; 选择Screencast&#xff08;录屏&#xff09; Fullscreen&#xff08;全屏&#xff09;-----Windows&#xff08;窗口&#xff09;--------Ar…

1、传统锁回顾(Jvm本地锁,MySQL悲观锁、乐观锁)

目录 1.1 从减库存聊起1.2 环境准备1.3 简单实现减库存1.4 演示超卖现象1.5 jvm锁1.6 三种情况导致Jvm本地锁失效1、多例模式下&#xff0c;Jvm本地锁失效2、Spring的事务导致Jvm本地锁失效3、集群部署导致Jvm本地锁失效 1.7 mysql锁演示1.7.1、一个sql1.7.2、悲观锁1.7.3、乐观…

fragment

fragment 在vue2中,组件必须有一个跟标签在vue3中,组件可以没有跟标签,内部会将多个标签包含在一个fragment虚拟元素中好处:减少标签层级,减小内存占用 teltport 什么是teltport teleport是一种能够将我们组件html结构移动到指定位置的技术 像是下面的代码不适用teleport:…

信息系统项目管理师(第四版)教材精读思维导图-第三章信息系统治理

请参阅我的另一篇文章&#xff0c;综合介绍软考高项&#xff1a; 信息系统项目管理师&#xff08;软考高项&#xff09;备考总结_计算机技术与软件专业技术_铭记北宸的博客-CSDN博客 目录 3.1 IT治理 3.2 IT审计 3.1 IT治理 3.2 IT审计

Java程序设计六大原则设计模式

Java程序设计六大原则 一、单一职责原则&#xff1a; 一个接口或者类只有一个原因引起变化&#xff0c;即一个接口或者类只有一个职责&#xff0c;负责一件事情。&#xff08;此原则同样适用于方法&#xff09; 好处&#xff1a;1、复杂性降低&#xff1b;2、可读性提高&…

elasticsearch查询操作(API方式)

说明&#xff1a;elasticsearch查询操作除了使用DSL语句的方式&#xff08;参考&#xff1a;http://t.csdn.cn/k7IGL&#xff09;&#xff0c;也可以使用API的方式。 准备 使用前需先导入依赖 <!--RestHighLevelClient依赖--><dependency><groupId>org.ela…

内存泄漏是什么?有什么危害

内存泄漏是什么&#xff1f;有什么危害 1. 前言1.内存泄漏是什么&#xff1f;2. 为什么会发生内存泄漏3. 内存泄漏的危害4. 总结 1. 前言 在各种项目开发中&#xff0c;内存泄漏是一个很严重的问题。对资源管理、性能优越、系统稳定性&#xff0c;以及是否安全产生极大印象。本…

AndroidStudio设计一个计算器

界面设计 activity_calcuator.xml 设计&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto&qu…

2、基于redis实现分布式锁

目录 2.1. 基本实现2.2. 防死锁2.3. 防误删2.4. redis中的lua脚本2.4.1 redis 并不能保证2.4.2 lua介绍 2.5. 使用lua保证删除原子性 2.1. 基本实现 借助于redis中的命令setnx(key, value)&#xff0c;key不存在就新增&#xff0c;存在就什么都不做。同时有多个客户端发送setn…

Easy-Es笔记

一、Easy-ES概述 Easy-Es&#xff08;简称EE&#xff09;是一款由国内开发者打造并完全开源的ElasticSearch-ORM框架。在原生 RestHighLevelClient 的基础上&#xff0c;只做增强不做改变&#xff0c;为简化开发、提高效率而生。Easy-Es采用和MP一致的语法设计&#xff0c;降低…

HDFS异构存储详解

异构存储 HDFS异构存储类型什么是异构存储异构存储类型如何让HDFS知道集群中的数据存储目录是那种类型存储介质 块存储选择策略选择策略说明选择策略的命令 案例&#xff1a;冷热温数据异构存储对应步骤 HDFS内存存储策略支持-- LAZY PERSIST介绍执行使用 HDFS异构存储类型 冷…

C# winform子窗口向父窗口传值

这里我使用一个简单的方法。只需要在父窗口定义一个静态变量就行。 父窗体为Form1,子窗体为Form2。 public static int get_num0; 子窗体直接给get_num赋值即可。 Form1.get_num2; 这样父窗体就能获得get_num修改后这个值了

[start] m40 test

software & update 470 drive version # cd /etc/apt # mv sources.list sources.list.bak # sudo vi /etc/apt/sources.list # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ja…

Flask 笔记

Flask 笔记 一、Flask介绍 1、学习Flask框架的原因 2020 Python 开发者调查结果显示Flask和Django是Python Web开发使用的最主要的两个框架。 2、Flask介绍 ​ Flask诞生于2010年&#xff0c;是Armin ronacher用Python 语言基于Werkzeug工具箱编写的轻量级Web开发框架。 ​…

Matlab 点云平面特征提取

文章目录 一、简介二、实现代码2.1基于k个邻近点2.2基于邻近半径参考资料一、简介 点云中存在这各种各样的几何特征,这里基于每个点的邻域协方差来获取该点的所具有的基础几何特征(如下图所示),这样的做法虽然不能很好的提取出点云中的各个部分,但却是可以作为一种数据预处…

SAP ABAP 用户状态锁定案例

一、前言 项目需求是根据当天及前两天的离职员工信息&#xff08;假设这是一个定时器任务每天下午5点执行程序&#xff0c;计算前两天的员工工号是为了将5点之后办理离职的员工工号找出来&#xff09;&#xff0c;将这些员工在用户表 USR02 中的锁定状态设置为 “64”&#xff…

Emacs之实现鼠标/键盘选中即拷贝外界内容(一百二十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

springboot整合ELK+kafka采集日志

一、背景介绍 在分布式的项目中&#xff0c;各功能模块产生的日志比较分散&#xff0c;同时为满足性能要求&#xff0c;同一个微服务会集群化部署&#xff0c;当某一次业务报错后&#xff0c;如果不能确定产生的节点&#xff0c;那么只能逐个节点去查看日志文件&#xff1b;lo…

SecureCRT如何将复制的内容粘贴到word中仍然保持原有字体颜色

SecureCRT如何将复制的内容粘贴到word中仍然保持原有字体颜色 QQ 109792317 说明&#xff1a;当SecureCRT加载了配色文件后&#xff0c;输出的关键字会被不同颜色高亮显示&#xff0c;但是如果复制粘贴到word中会发现成了纯文本&#xff0c;字体颜色消失了。 如何保留 &#x…