总结
为了方便使用,把结论和代码放在前面,而讲解放在后面。
- CMakeLists:在catkin_make期间生成文件,如xxxConfig.Cmake导出本包的资源 加入到
catkin_INCLUDE_DIRS
和catkin_LIBRARIES
,find_package本包依赖所需依赖(包含依赖包并不会递归其依赖的子包为依赖,因为CMakeLists是独立的)。 - Package.xml:是了解一个包的所有入口,依赖项可以用来解决包之间的编译和执行顺序,包含某个包会自动递归其所依赖的子包作为依赖。
- 因此在Package.xml声明依赖(包间依赖关系)和CMakeLists中find_package(包所需依赖)都要有,否则前者导致编译顺序出错,后者导致无头文件目标文件链接失败。
应用包中:
CMakeLists:
find_package(catkin REQUIRED COMPONENTS
my_dep
)
include_directories(include ${catkin_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME}_node ${catkin_LIBRARIES})
---
Package.xml:
<buildtool_depend>catkin</buildtool_depend>
<build_depend>my_dep</build_depend>
<exec_depend>my_dep</exec_depend>
被依赖包中:
CMakeLists:
catkin_package(
INCLUDE_DIRS include
LIBRARIES my_dep
# CATKIN_DEPENDS ros_cpp ros_py std_msgs
# DEPENDS system_lib
)
---
Package.xml:
<buildtool_depend>catkin</buildtool_depend>
按实际需求填写
提示:如果用clion可能发生终端中catkin_make能通过,但是clion中自动cmake栏提示找不到依赖包,可能可以通过关闭当前clion,从对于source过的ws启动clion
来解决
前言
在开发ROS程序时,有时候希望把一个流程通过分成几个包来完成,比如点云物体识别时
- 获取数据进行预处理和拼接
- DNN部分包
- 输出处理可视化和其他后期功能
- ...
但是以上各个part的连接,需要每个包中都有一个node且包含topics/srv/action等这样才能在ros中交互。当软件比较复杂的时候,可能还会分的更细,这样我们就会有一堆的node,虽然说可以通过launch文件来进行批量启动,但是还存在几个问题:
- 不整洁,起码看着很冗余。
- 通信是要占用资源的,让费。
- ...
因此除非是两个part之间是不同语言完成的,比如DNN部分用pytorch而某个部分是cpp库写的,这样整合两个不同语言的程序用两个node来连接是可以接受的。
但是如果只是单纯的想把一个Cpp程序干净的分为几个part,那么不妨使用本文的方法,即创建的package只包含lib而不含node可执行文件(好像没差)。
其实直接在某个包内把源文件生成各种lib然后手动链接也是一样的。
target_link_libraries(${PROJECT_NAME}_node
oslam ${ALL_LIBS}
)
但是写成ROS库就可像调ROS的API一样,更具有通用性?更具有移植性?更贴近ROS框架?
find_package(catkin REQUIRED COMPONENTS
my_dep
...
)
#然后所有的ROS依赖包头文件和库文件都包含在宏 ${catkin_INCLUDE_DIRS} ${catkin_LIBRARIES}
背景
首先资料放送:catkin详解0,catkin详解1,catkin详解2,ROS包形式2详解,
然后我们知道ROS包中有两个文件是重要的
- CMakeLists.txt是cmake编译框架下的文件,而catkin是cmake加入了一些宏命令来适配ROS(个人理解)。因此在CMakeLists中写入catkin支持的宏如
catkin_package
add_service_files
generate_messages
等会自动帮你生成一些文件 - package.xml才是ROS包的命根子,无论是
rospack
rosrun
,catkin_make
等ros中用的命令,甚至是roslaucnh
中的$(find package)
都是通过搜索ros_path
下的所有文件夹中的package.xml
的。然后通过该文件来获取程序包
信息。
CMakeLists
然后我们来看看CMakeLists在catkin编译系统下相比cmake编译系统下有哪些特殊的点
首先就是多了:
find_package(catkin REQUIRED COMPONENTS
...
)
和普通cmake
下一样,find_package
来寻找catkin
环境中xxxConfig.Cmake
来寻找ROS包,比如roscpp rospy std_msgs
。然后将找到的包中在xxxConfig.Cmake
中指定头文件和库文件等依赖
包含到对应的${catkin_INCLUDE_DIRS}
和${catkin_LIBRARIES}
中。而xxxConfig.Cmake
文件是在ws中进行catkin_make
会自动生成的文件 。在cmake体系中,find_package能找到的包,一般都是在cmake搜索目录如/usr/local/lib/cmake
(也可以自己设定cmake的Module路径)搜对应的xxxConfig.cmake
或findxxx.cmake
。
然后是
#生产 消息类型/服务类型/动作类型的宏
add_message_files(FILES Message1.msg)
add_service_files( FILES Service1.srv)
add_action_files(FILES Action1.action )
generate_messages(DEPENDENCIES std_msgs)
再就是在add_library
和add_exacutable
前调用的
catkin_package(
INCLUDE_DIRS include #- 导出包的include路径
LIBRARIES my_dep_app #- 导出项目中的库
CATKIN_DEPENDS my_dep #- 该项目依赖的其他catkin项目
DEPENDS system_lib #- 该项目所依赖的非catkin CMake项目,如普通的opencv库。
)
如果指定了INCLUDE_DIRS
和LIBRARIES
则catkin_make
产生对应xxxConfig.Cmake
时会此处的include目录
和本库产生的库文件
加入到xxxConfig.Cmake
的list中如下图
然后别的包通过find_package
就可以在那两个宏中得到所依赖库对应的头文件和库文件。
package.xml
其余信息都比较显然这里说说比较特殊的也就是依赖项,我们知道catkin_make的时候每个包或说CMakeLists是作为一个个体进行独立编译的,而且编译顺序是按字母排序的即它不知道那些包之间有先后关系。如果你的功能包依赖于某个catkin库
则需要在package.xml
的依赖中写清楚,这样catkin_make
的时候就会自动帮你把顺序捋清楚咯。
其中depend
=build_depend
+exec_depend
<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:指定编译工具为catkin
- build_depend:编译时依赖,比如
message_generation
先编译所依赖的包再编译本包 - build_export_depend:编译导出依赖,本包需要导出(被依赖),因此被导出的那部分的依赖为。
- exec_depend:执行依赖(解释性语言如python脚本只需要填写这个而无需填写两个build依赖)比如
message_runtime
是用来生成ros-msg消息代码的python文件
当你在xml中depend某个包,那么被依赖的包的依赖也会被导入到当前包中可用rospack depend xxx
查询
如果不加build_depend
可能也能编过,这是因为命名使得默认顺序对了,但是谁能保证命名不同后顺序一直是对的呢?
此外package.xml下的export
标签用处可以看看这个pluginlib