Tổ chức nút C++ trong ROS2 bằng cách sử dụng gói phần mềm

Trong hệ thống ROS2, ngôn ngữ C++ là một trong những lựa chọn hàng đầu để xây dựng các nút có hiệu suất cao. Bài viết này sẽ hướng dẫn chi tiết cách tạo, cấu hình, biên dịch và thực thi các gói phần mềm kiểu C++ trong ROS2, phân tích cấu trúc và quy trình xây dựng, đồng thời so sánh sự khác biệt giữa nút C++ và Python, kèm theo giải thích cơ chế biến môi trường của ROS2.

Tạo gói phần mềm C++

Sử dụng lệnh ros2 pkg create để tạo gói C++ với hệ thống xây dựng ament_cmake:

ros2 pkg create example_cpp_pkg --build-type ament_cmake --license MIT
  • --build-type ament_cmake: Chọn hệ thống xây dựng ament_cmake phù hợp cho C++.
  • --license MIT: Xác định loại giấy phép sử dụng.

Sau khi thực hiện lệnh, cấu trúc thư mục được tạo ra như sau:

example_cpp_pkg/
├── include/example_cpp_pkg/  # Thư mục chứa file header C++
├── src/                      # Thư mục chứa file nguồn C++
│   └── my_cpp_node.cpp       # File nguồn nút C++ cần viết
├── CMakeLists.txt            # File cấu hình xây dựng chính bằng CMake
├── LICENSE                   # File giấy phép
└── package.xml               # File thông tin mô tả gói phần mềm

Cấu trúc gói phần mềm C++

File/Thư mục Mô tả chức năng
include/example_cpp_pkg/ Lưu trữ các file header C++, dùng để khai báo giao diện và định nghĩa lớp giữa các module.
src/ Lưu trữ các file nguồn C++, chứa logic nghiệp vụ của nút.
CMakeLists.txt Xác định quy tắc biên dịch, tìm kiếm phụ thuộc, tạo file thực thi và các logic xây dựng khác, là file cấu hình trung tâm của gói C++.
package.xml Khai báo tên gói, phiên bản, người duy trì, phụ thuộc và các thông tin mô tả khác.
LICENSE Xác định quyền sử dụng, sửa đổi và phân phối mã nguồn (ví dụ ở đây là MIT).

Viết mã nút C++

Tạo file my_cpp_node.cpp trong thư mục src/, viết logic cơ bản cho nút C++:

#include "rclcpp/rclcpp.hpp"

int main(int argc, char **argv_ptr)
{
    rclcpp::init(argc, argv_ptr);
    auto node_instance = std::make_shared("my_cpp_node");
    RCLCPP_INFO(node_instance->get_logger(), "Xin chao tu nút C++!");
    rclcpp::spin(node_instance);
    rclcpp::shutdown();
    return 0;
}

Cấu hình package.xml thêm phụ thuộc

Mở file package.xml, thêm khai báo phụ thuộc cho thư viện khách hàng C++ rclcpp:

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <!-- Thông tin khác (tên, phiên bản, người duy trì, v.v.) -->
  <license>MIT</license>
  <depend>rclcpp</depend>
  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <!-- Các cấu hình khác -->
</package>

Cấu hình CMakeLists.txt (Chú ý: ament_cmake và ament_target_dependencies)

Mở file CMakeLists.txt, cấu hình quy tắc biên dịch và phụ thuộc:

cmake_minimum_required(VERSION 3.9)
project(example_cpp_pkg)

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)

add_executable(my_cpp_node src/my_cpp_node.cpp)

ament_target_dependencies(my_cpp_node rclcpp)

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

ament_package()
  • ament_target_dependencies(tên_nút tên_phụ_thuộc): Là lệnh cấu hình cốt lõi trong gói C++ của ROS2, tự động xử lý đường dẫn header và liên kết thư viện của rclcpp, cách này vẫn tương thích với môi trường ROS2 ngay cả khi kết hợp với lệnh CMake truyền thống.
  • install(...): Cài đặt file thực thi vào thư mục lib/${PROJECT_NAME}, đảm bảo ros2 run có thể tìm thấy nút.

Biên dịch gói: colcon build so với CMake truyền thống

Khuyến nghị: Sử dụng colcon build

Thực hiện trong thư mục gốc không gian làm việc:

colcon build

Sau khi thành công, đầu ra tương tự như:

Starting >>> example_cpp_pkg
Starting >>> example_python_pkg
Finished <<< example_cpp_pkg [0.38s]
Finished <<< example_python_pkg [0.65s]
Summary: 2 packages finished [0.78s]

Ưu điểm: colcon tự động quản lý thứ tự xây dựng nhiều gói và biến môi trường, là phương pháp xây dựng tiêu chuẩn cho không gian làm việc ROS2.

Biên dịch CMake truyền thống (chỉ để tham khảo)

Nếu tạo thủ công thư mục build và thực thi CMake:

mkdir build && cd build
cmake ..
make

Cách này có thể biên dịch ra file thực thi nhưng cần cấu hình thủ công biến môi trường để được công cụ ROS2 nhận diện, không khuyến nghị sử dụng riêng lẻ trong hệ sinh thái ROS2.

Biến môi trường và chạy nút

Chạy trực tiếp file thực thi đã cài đặt

Sau khi xây dựng hoàn tất, file thực thi nằm tại thư mục install/example_cpp_pkg/lib/example_cpp_pkg. Dùng lệnh ldd để xem phụ thuộc thư viện đã liên kết đúng chưa:

ldd install/example_cpp_pkg/lib/example_cpp_pkg/my_cpp_node

Nếu các phụ thuộc (như librclcpp.so) đều được liên kết đúng, có thể chạy trực tiếp:

install/example_cpp_pkg/lib/example_cpp_pkg/my_cpp_node

Đầu ra trên terminal:

[INFO] [1680684100.228612032] [my_cpp_node]: Xin chao tu nút C++!

Biến môi trường AMENT_PREFIX_PATH và ros2 run

Thực hiện lệnh source để cấu hình biến môi trường:

source install/setup.bash

Lệnh này sẽ chỉnh sửa biến môi trường AMENT_PREFIX_PATH, thêm đường dẫn cài đặt của gói vào đường dẫn tìm kiếm gói của ROS2. Có thể kiểm tra qua lệnh:

echo $AMENT_PREFIX_PATH

Đầu ra tương tự:

/home/user/install/example_cpp_pkg:/opt/ros/humble

Bây giờ có thể dùng ros2 run để chạy nút:

ros2 run example_cpp_pkg my_cpp_node

Cũng có thể dùng lệnh ros2 pkg prefix để xem thư mục tiền tố cài đặt của gói:

ros2 pkg prefix example_cpp_pkg

Đầu ra là thư mục gốc cài đặt của gói (ví dụ /home/user/install/example_cpp_pkg).

Phân tích sự khác biệt giữa nút C++ và Python

File thực thi của nút C++ có thể chạy trực tiếp, trong khi nút Python thường cần cấu hình môi trường bổ sung, nguyên nhân cốt lõi là:

Đặc điểm Nút C++ (biên dịch) Nút Python (thông dịch)
Xử lý phụ thuộc Liên kết thư viện phụ thuộc vào file thực thi lúc biên dịch (có thể xác minh qua ldd) Cần tìm module phụ thuộc qua PYTHONPATH lúc chạy
Điều kiện chạy Chỉ cần file thực thi (phụ thuộc đã được liên kết) Cần cấu hình PYTHONPATH hoặc chạy script môi trường source để trình thông dịch tìm thấy module

Thẻ: ros2 cmake C++ ament package-management

Đăng vào ngày 23 tháng 5 lúc 22:42