如何在ROS2调用第三方C++库 - 简易版

假设在ros_ws下有src文件夹,结构如下:

src
├── add_node // 调用库的publish节点
└──  lib_tut //库

生成库

用lib_tut生成第三方库,结构如下:

src/lib_tut/
├── CMakeLists.txt
├── include
│   └── lib_tut
│       └── add.h
├── package.xml
└── src
    └── add.cpp

add.cpp定义了一个add()函数,如下:

# include "add.h"

int add(int a, int b){
    return a+b;
}

其中CMakeLists.txt中,除了ros2 pkg create lib_tut生成的默认内容外,在ament_package()前追加如下代码:

include_directories(include/lib_tut) # 头文件
add_library(asdf src/add.cpp) # 库的名字随便,这里用asdf
ament_export_targets(asdf HAS_LIBRARY_TARGET)
install(
  DIRECTORY include/lib_tut
  DESTINATION include
)

install(
  TARGETS asdf
  EXPORT asdf
  ARCHIVE DESTINATION lib 
  INCLUDES DESTINATION include
)

在ros_ws运行colcon build --packages-select lib_tut即可生成库,库及头文件位于install/lib_tut下的include和lib中。

调用库

add_node文件结构如下:

src/add_node/
├── CMakeLists.txt
├── include
│   └── add_node // 空文件夹
├── package.xml
└── src
    └── pub_add.cpp

pub_add.cpp是一个简单的调用asdf库中的add()函数并发布的节点,来自官方demo,代码如下:

#include <chrono>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include"lib_tut/add.h"

using namespace std::chrono_literals;

/* This example creates a subclass of Node and uses std::bind() to register a
 * member function as a callback from the timer. */

class MinimalPublisher : public rclcpp::Node
{
public:
  MinimalPublisher()
  : Node("minimal_publisher"), count_(0)
  {
    publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
    timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
  }

private:
  void timer_callback()
  {
    auto message = std_msgs::msg::String();
    message.data = "Hello, world! " + std::to_string(add(count_++, 100)); //唯一的改动地方
    RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
    publisher_->publish(message);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
  size_t count_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalPublisher>());
  rclcpp::shutdown();
  return 0;
}

CMakeLists.txt 增加如下代码:

set(lib_tut_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../install/lib_tut/share/lib_tut/cmake) #如报错找不到lib_tut的...Config.cmake文件,则加上这句
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(lib_tut REQUIRED) # 找的是package而不是lib

add_executable(pub_add src/pub_add.cpp)
target_link_libraries(pub_add ${CMAKE_CURRENT_SOURCE_DIR}/../../install/lib_tut/lib/libasdf.a) #不确定是否需要
ament_target_dependencies(pub_add lib_tut rclcpp std_msgs)

install(TARGETS
  pub_add
  DESTINATION lib/${PROJECT_NAME}) #大概是ROS专用写法

接下来运行:

colcon build --packages-select add_node # 完成编译节点

然后运行节点即可正常发布:

ros2 run add_node pub_add 

运行结果如下:

[INFO] [1710496025.004874966] [minimal_publisher]: Publishing: 'Hello, world! 100'
[INFO] [1710496025.504840260] [minimal_publisher]: Publishing: 'Hello, world! 101'
[INFO] [1710496026.004873753] [minimal_publisher]: Publishing: 'Hello, world! 102'
[INFO] [1710496026.504945355] [minimal_publisher]: Publishing: 'Hello, world! 103'

其他方法

可以使用set(libxxx_DIR $(dir to libxxxConfig.cmake))的方式使得find_package()找到第三方库。

标准库的使用方法(例:RVO2)

进入项目根目录,使用cmake -B build在build文件夹编译。
进入build,sudo make install,即可安装到系统目录/usr/local/lib/usr/local/include下。
自定义项目的CMakeLists.txt:

add_executable(blocks src/Blocks.cpp)
target_link_libraries(blocks RVO)
ament_target_dependencies(blocks rclcpp) #用了这句话就不用在package.xml加depend了。例如报错找不到rclcpp就在此加上。

install(TARGETS
  blocks
  DESTINATION lib/${PROJECT_NAME}) # 安装ROS节点
ament_package()

在一个包中同时使用python和cpp

中文解决方案
英文解决方案,需翻
package.xml中需包含以下:

 <buildtool_depend>ament_cmake</buildtool_depend>
 <buildtool_depend>ament_cmake_python</buildtool_depend>

 <depend>ros2_interfaces</depend>
 <depend>rclcpp</depend>
 <depend>rclpy</depend>

文件结构:

# 包名为roscpp
├── CMakeLists.txt
├── include
│   └── roscpp 
│       └── RVO.h
├── package.xml
├── roscpp 
│   ├── __init__.py 
│   └── utils.py //需导的包
├── scripts
│   └── draw_plot.py //python脚本,导包时直接from roscpp.utils import *
└── src
    └── pub_pos.cpp //cpp文件

CMakeLists.txt需包含:

find_package(rclpy REQUIRED)

#python install
ament_python_install_package(${PROJECT_NAME}) 
install(PROGRAMS
  scripts/draw_plot.py
  DESTINATION lib/${PROJECT_NAME})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容