如何在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})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容