鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    一文讲透,ROS2工程引入第三方库,如何编写CMakeLists.txt

    已定时 已固定 已锁定 已移动
    ROS 2相关问题
    ros2 cmakelists 第三方库 工程实践
    2
    2
    2.0k
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 小鱼小
      小鱼 技术大佬
      最后由 编辑

      一文讲透,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在工程实践中遇到的速率不够,丢数据问题如何解决。

      新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

      1 条回复 最后回复 回复 引用 0
      • 2
        2447383421
        最后由 编辑

        这篇帖子的源代码可以给我参考一下吗

        1 条回复 最后回复 回复 引用 0
        • 第一个帖子
          最后一个帖子
        皖ICP备16016415号-7
        Powered by NodeBB | 鱼香ROS