ros2调用自定义外部链接库.so库(自定义库)

由于最近需要使用别人写好的库,所以特地来验证一下,在ros2中如何使用自定义的库。

1、文件结构

首先我有两个功能包、自定义消息

说明一下功能:vehicle功能包是每秒发布两个整数。

                          calculation功能包是订阅vehicle发布的话题,并计算两个整数的和。

那么好了,关于计算两个整数的和,我采用外部库来实现。那么首先你就得有库文件和头文件吧,有库你才可以调用。下面我来说一下我的库。关于生成动态库的步骤我就不说了。自行百度。

add.h 和 libaddlib.so是我所需要的,又因为,只有calculation功能包是需要调用这个库的,所以只关心calculation功能包就够了。

2、新建文件

在calculation功能包中新建,一个add.h文件,一个文件夹,下面包含libaddlib.so库文件。

下面是calculation功能包的结构:

另外一种表示方法更直观,可以看出calculation功能包中个文件的关系:

所以,只需要修改CMakeList.txt就可以了。

3、修改calculation功能包的CMakeList.txt(重点)

    • find_library 是 CMake 提供的命令,用于在系统上查找指定的库文件。
    • ADD_LIB 是你将要在 CMake 中定义的一个变量,用于存储找到的库文件的路径。
    • addlib 是你要查找的库文件的名称。
    • PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib 指定了查找库文件的路径。${CMAKE_CURRENT_SOURCE_DIR} 是一个 CMake 变量,表示当前处理的 CMakeLists.txt 文件所在的目录的路径。这里指定在当前 CMake 文件所在目录下的 lib 子目录中查找库文件。

总体而言,这行代码的目的是在 ${CMAKE_CURRENT_SOURCE_DIR}/lib 目录中查找名为 addlib 的库文件,并将找到的库文件的路径存储在 ADD_LIB 变量中。在后续的 CMake 文件中,你可以使用这个变量来确保链接你的可执行文件或库。

target_link_libraries 用于将目标(通常是一个可执行文件或库)与一个或多个库进行链接。

  • calculate_node 是你的可执行文件的名称或目标的名称。
  • ${ADD_LIB} 是你之前使用 find_library 命令找到的库的路径,通过该变量告诉 CMake 链接器库的位置。
  • addlib 是你要链接的库的名称。

这一行的目的是将可执行文件 calculate_node 与名为 addlib 的库进行链接。${ADD_LIB} 指定了库的路径,确保链接器能够找到它。这样,当你运行 calculate_node 时,系统将能够正确地定位并加载 addlib 库。

把CMakeList.txt修改成这样应该就可以了。

分享一下完整的calculation功能包中的cmakelist.txt  

cmake_minimum_required(VERSION 3.5)
project(calculation)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(intadd_interfaces REQUIRED)
find_library(ADD_LIB addlib PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # uncomment the line when a copyright and license is not present in all source files
  #set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # uncomment the line when this package is not in a git repo
  #set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()
# 设置包含目录
include_directories(include)

add_executable(calculate_node src/calculate.cpp)
ament_target_dependencies(calculate_node 
            rclcpp 
            std_msgs 
            intadd_interfaces
            )
target_link_libraries(calculate_node ${ADD_LIB} addlib)

install(TARGETS
      calculate_node
      DESTINATION lib/${PROJECT_NAME}
      )


# 安装头文件
install(DIRECTORY include/ DESTINATION include/${PROJECT_NAME})

4、导入外部库的路径(非必须,报错的话看这步)

但是我在运行时又出现了问题,就是找不到这个库文件,所以要把库文件的路径添加到环境变量中去:

先看一下库文件的路径:pwd

在终端输入:

export LD_LIBRARY_PATH=/home/shnavi/ml/driverless/src/calculation/lib:$LD_LIBRARY_PATH

即:

5、效果如下

这样就可以了,试试效果:

启动calculation功能包来计算两数之和:

启动vehicle包,每隔一秒发送两个整数:

文中使用的话题是自定义消息:

 

6、头文件目录

这样就成功调用了自定义的库函数,下面分享一下头文件:

自定义库的头文件这样定义就可以了。

7、部分测试代码

秉持开源精神,所以把源文件分享一下,供大家测试:

calculate.cpp

#include "rclcpp/rclcpp.hpp"
#include "intadd_interfaces/msg/add.hpp"
#include "calculation/add.h"  // 包含新创建的头文件

class Calculation : public rclcpp::Node
{
public:
    Calculation(std::string name) : Node(name)
    {
        RCLCPP_INFO(this->get_logger(), "%s", name.c_str());

        // 创建一个名称为"integer_subscriber"、队列大小为10的话题订阅者
        subscriber_ = this->create_subscription<intadd_interfaces::msg::Add>(
            "integer_publisher",
            10,
            [this](const intadd_interfaces::msg::Add::SharedPtr msg) {
                // Callback function when receiving a message
                int result = add_numbers(msg->first, msg->second);  // Call the add_numbers function
                RCLCPP_INFO(this->get_logger(), "Received: %d and %d, Sum: %d", msg->first, msg->second, result);
            }
        );

    }

private:
    rclcpp::Subscription<intadd_interfaces::msg::Add>::SharedPtr subscriber_;
};

int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    auto node = std::make_shared<Calculation>("vehicle");
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

其中下面圈出来的就是库中的函数,直接调用就可以了。

vehicle.cpp

#include "rclcpp/rclcpp.hpp"
#include "intadd_interfaces/msg/add.hpp"
#include <random>  // 包含随机数生成器

class VehicleNode:public rclcpp::Node
{
public:
    //构造函数
    VehicleNode(std::string name) : Node(name) //
    {
        //打印名字信息
        RCLCPP_INFO(this->get_logger(),"%s",name.c_str());
        // 创建一个名称为"integer_publisher"、队列大小为10的话题发布者
        publisher_ = this->create_publisher<intadd_interfaces::msg::Add>("integer_publisher", 10);
        
        // 使用定时器每秒发布两个随机整数
        timer_ = this->create_wall_timer(
            std::chrono::seconds(1),
            [this]() {
                auto message = intadd_interfaces::msg::Add();
                // Generate and publish two random integers
                message.first = generateRandomInteger();
                message.second = generateRandomInteger();
                RCLCPP_INFO(this->get_logger(), "Publishing random integers: %d and %d", message.first, message.second);
                publisher_->publish(message);
            }
        );
    }
    
private:
    //声明一个发布者
    rclcpp::Publisher<intadd_interfaces::msg::Add>::SharedPtr publisher_;
    //声明一个定时器
    rclcpp::TimerBase::SharedPtr timer_;
     // 生成随机整数的辅助函数
    int generateRandomInteger()
    {
        // 使用C++11的随机数引擎和分布
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<int> dist(1, 100);  // 生成1到100之间的整数
        return dist(gen);
    }

};

int main(int argc,char** argv)
{
    rclcpp::init(argc,argv);
    auto node = std::make_shared<VehicleNode>("vehicle");
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;

}

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值