一文讲透,ROS2工程引入第三方库,如何编写CMakeLists.txt
大家好,我是爱学习爱劳动的小鱼,今天换个口味,来点ROS 2 跟工程实践相关的。
具体需求是这样的,最近的项目有用到 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在工程实践中遇到的速率不够,丢数据问题如何解决。