小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
一文讲透,ROS2工程引入第三方库,如何编写CMakeLists.txt
-
一文讲透,ROS2工程引入第三方库,如何编写CMakeLists.txt
大家好,我是爱学习爱劳动的小鱼,今天换个口味,来点ROS 2 跟工程实践相关的。
今年是2024年,以后的文章没有意外就放到 20:24 发,2024记得锁定 20:24 分的《鱼香ROS》哦~
具体需求是这样的,最近的项目有用到 USB 转 CAN 的设备,用的驱动是几个 .so 的动态链接库。
最终部署的平台有amd64和arm64之分,开发的时候用的电脑是amd64架构,最终使用的是 arm64 系统。
所以这里就涉及了两个问题
1.如何在 ROS 2 的工程中引入第三方的CAN驱动库
2.针对不同平台,如何编写CMake 实现,自动根据平台选择动态库
对于第一个问题,我们知道,在创建ROS 2功能包的时候,自动选择的构建类型是 ament_cmake
ament_cmake 链接库的方式是使用 ament_target_dependencies
CMakeLists.txt 默认使用链接库的方式是 target_link_libraries
所以你可以认为 ament_target_dependencies 是专门用于链接ROS 2 的库, target_link_libraries 用于链接普普通通的第三方库。
看一下卖家提供的驱动库
. ├── libcanbus.a ├── libcanbus.so ├── libusb-1.0.a ├── libusb-1.0.la ├── libusb-1.0.so ├── libusb-1.0.so.0 └── libusb-1.0.so.0.3.0 0 directories, 7 files
USB 库+CANBUS动态库
现在创建一个功能包,名字就叫 candriver
然后在功能包下新建 lib 目录,把所有的库文件拷贝进去
对了,卖家还提供了 arm64的库,一样的,新建 libarm,把库拷贝进去
然后把卖家提供的头文件放在include目录下,然后在是src下新建cantest.cpp下 最终得到如下目录结构
├── CMakeLists.txt ├── include │ ├── canbus.h │ └── candriver ├── install_lib.sh ├── lib │ ├── libcanbus.a │ ├── libcanbus.so │ ├── libusb-1.0.a │ ├── libusb-1.0.la │ ├── libusb-1.0.so │ ├── libusb-1.0.so.0 │ └── libusb-1.0.so.0.3.0 ├── libarm │ ├── libcanbus.a │ ├── libcanbus.so │ ├── libusb-1.0.a │ ├── libusb-1.0.la │ ├── libusb-1.0.so -> libusb-1.0.so.0.3.0 │ ├── libusb-1.0.so.0 -> libusb-1.0.so.0.3.0 │ └── libusb-1.0.so.0.3.0 ├── package.xml ├── src │ └── cantest.cpp ├── test
接着我们来编写CMakeLists
要让代码找到头文件,加这句话
include_directories(include)
要添加可执行文件
add_executable(cantest src/cantest.cpp )
要链接ROS2的库,先find_package,再添加ament_target_dependencies
要链接支持find_package 的第三方库,要用target_link_libraries来链接
find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(guidebot_interfaces REQUIRED) ament_target_dependencies(cantest rclcpp guidebot_interfaces )
对于不支持的,要先找到对应库路径,我们放到工程目录下,可以直接通过CMakeLists.txt提供的${PROJECT_SOURCE_DIR}获取路径,拼接lib即可获取库
加上link所以这样写
set(CAN_LIB lib) message(STATUS "Linking libraries...") target_link_libraries(cantest ${PROJECT_SOURCE_DIR}/${CAN_LIB}/libcanbus.so ${PROJECT_SOURCE_DIR}/${CAN_LIB}/libusb-1.0.so )
如果你这样直接编译,是没有问题的,但最后运行的时候就会无法link,这是因为src目录下的库目录没有被 ROS 2的 setup.bash 添加到搜索目录
那问题来了,ROS 2 搜索哪些目录?
你随便source 一下setup.bash
然后echo $LD_LIBRARY_PATH
找找可以看到 /home/fishros/guidebot/install/candriver/lib
所以这个目录 install/candriver/lib 就是ROS2 运行期间会检索动态链接库的目录
知道了就可以把库拷贝过去
# 安装库文件 message(STATUS "Installing libraries...") install(DIRECTORY ${CAN_LIB}/ DESTINATION lib/ )
好的,此时再构建和运行就没问题了,我们的第一个问题就解决了
接着第二个问题,如果保证不同架构可以用同一份代码(这个还设计如果交叉编译,如何发布ROS2的工程等等,以后再说,有空了可以出一个ROS2工程实践系列)
这里我们还是从 CMakeLists.txt 动手
这样干
# 判断是否为arm64系统 message(STATUS "Checking if the system is aarch64...") if(CMAKE_SYSTEM_PROCESSOR MATCHES aarch64) message(STATUS "The system is aarch64!") set(CAN_LIB libarm) else() message(STATUS "The system is not aarch64.") set(CAN_LIB lib) endif()
最后记得安装可执行文件
install(TARGETS cantest RUNTIME DESTINATION lib/${PROJECT_NAME} )
好了,到这里就把ROS2如何使用第三方库给讲清楚了,欢迎留言,下次抽空讲讲ROS 2在工程实践中遇到的速率不够,丢数据问题如何解决。
-
这篇帖子的源代码可以给我参考一下吗