假设在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})