Atlas Robotics
ROS2 PackageTrung bình

Launch File trong ROS2 — khởi động nhiều node cùng lúc

Atlasbot · 17/8/2026 · 11 phút đọc

Launch File trong ROS2 — khởi động nhiều node cùng lúc
Một launch file khởi động nhiều node cùng lúc

Robot Mecanum hay Diff Robot trong phần showcase dự án đều chạy song song nhiều node: driver động cơ, LiDAR, SLAM, Nav2... Mở từng terminal gõ ros2 run cho từng node là không thực tế. Launch file giải quyết đúng vấn đề này — khai báo toàn bộ node cần chạy, kèm tham số, trong một file Python, khởi động bằng một lệnh ros2 launch.

Khái niệm chính

Đặt trong thư mục launch/ của package, ví dụ launch/bringup.launch.py:

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package="my_cpp_pkg",
            executable="hello_node",
            name="hello_node",
            output="screen",
        ),
        Node(
            package="my_py_pkg",
            executable="hello_node",
            name="hello_node_py",
            output="screen",
        ),
    ])

Chạy bằng:

ros2 launch my_cpp_pkg bringup.launch.py

Hàm bắt buộc phải tên generate_launch_description() — đây là điểm vào (entry point) mà ros2 launch tìm và gọi. Mỗi phần tử Node(...) tương đương một lần gõ ros2 run <package> <executable> thủ công.

Chỉ viết file thôi chưa đủ — phải khai install để launch file được copy vào install/ lúc build:

install(DIRECTORY launch
  DESTINATION share/${PROJECT_NAME})

Với package Python, tương đương trong setup.py:

data_files=[
    ("share/" + package_name + "/launch",
     ["launch/bringup.launch.py"]),
],

Tóm lại: Quên khai install(DIRECTORY launch ...) (C++) hoặc data_files (Python) là lỗi rất hay gặp — code Python launch file đúng cú pháp nhưng ros2 launch báo "package 'X' not found" vì file chưa từng được copy vào install/.

Nguyên lý hoạt động

Truyền tham số và include launch file khác:

from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    use_sim = DeclareLaunchArgument("use_sim", default_value="false")

    driver_node = Node(
        package="my_cpp_pkg",
        executable="hello_node",
        parameters=[{"use_sim": LaunchConfiguration("use_sim")}],
    )

    nav2 = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(["/path/to/nav2_bringup/launch/bringup_launch.py"])
    )

    return LaunchDescription([use_sim, driver_node, nav2])
  • DeclareLaunchArgument — khai một tham số dòng lệnh cho chính launch file (ros2 launch my_pkg bringup.launch.py use_sim:=true)
  • IncludeLaunchDescription — nhúng nguyên một launch file khác vào — cách chuẩn để "lắp ráp" launch file lớn (ví dụ bringup toàn hệ thống) từ nhiều launch file nhỏ của từng package con, thay vì copy dán lại toàn bộ node

Kiến thức kỹ thuật

Thông số

Bảng tổng hợp các action hay dùng nhất khi viết launch file:

ActionDùng để
NodeChạy một executable ROS2
DeclareLaunchArgumentKhai tham số dòng lệnh cho launch file
IncludeLaunchDescriptionNhúng launch file khác
TimerActionTrì hoãn chạy một action sau N giây
LogInfoIn log ra terminal lúc launch
ExecuteProcessChạy một tiến trình bất kỳ không phải node ROS2 (VD: script shell)
GroupActionGom nhiều node vào chung 1 namespace hoặc điều kiện bật/tắt

Ứng dụng thực tế

Kiến trúc launch file thực tế của một AMR thường theo mô hình phân tầng: 1 launch file gốc bringup.launch.py dùng IncludeLaunchDescription để gộp lại nhiều launch file con — sensors.launch.py (khởi động LiDAR, camera, IMU), navigation.launch.py (Nav2), safety.launch.py (node giám sát an toàn) — mỗi launch file con có thể test độc lập, và launch file gốc dùng DeclareLaunchArgument (VD: use_sim_time, enable_camera) để cùng 1 bộ launch file chạy được cả trên robot thật lẫn trong mô phỏng, chỉ khác giá trị tham số truyền vào lúc gọi lệnh.

Ví dụ thực tế

$ ros2 launch my_cpp_pkg bringup.launch.py use_sim:=true
Output:
[INFO] [launch]: All log files can be found below /home/user/.ros/log/...
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [hello_node-1]: process started with pid [12345]
[INFO] [hello_node_py-2]: process started with pid [12346]
[hello_node-1] [INFO] [1723000000.111] [hello_node]: hello_node đã khởi động
[hello_node_py-2] [INFO] [1723000000.222] [hello_node_py]: hello_node đã khởi động

Tiền tố [hello_node-1]/[hello_node_py-2] trước mỗi dòng log giúp phân biệt log của từng node dù chạy chung 1 terminal — số thứ tự (-1, -2) là thứ tự khai trong launch file, hữu ích khi cần xác định nhanh log nào thuộc node nào trong 1 hệ thống chạy hàng chục node cùng lúc.

Lỗi thường gặp

  • Quên khai install(DIRECTORY launch ...) hoặc data_files — như đã nói ở phần Khái niệm chính, đây là lỗi phổ biến nhất khiến ros2 launch không tìm thấy file dù cú pháp Python hoàn toàn đúng.
  • 1 node crash khiến toàn bộ launch "im lặng" khó chẩn đoán — nếu không nhìn kỹ log, dễ nhầm tưởng cả hệ thống bị treo trong khi thực chất chỉ 1 node lỗi và thoát sớm — luôn kiểm tra ros2 node list sau khi launch để xác nhận đủ số node đang chạy như mong đợi.
  • Nhầm tưởng LaunchConfiguration tự động đổi kiểu dữ liệu — giá trị truyền qua dòng lệnh (use_sim:=true) luôn là string "true", không tự động thành kiểu bool Python — nếu code kiểm tra if use_sim: theo kiểu Python thông thường mà không ép kiểu đúng cách, logic có thể sai (chuỗi "false" vẫn là truthy trong Python).
  • IncludeLaunchDescription tạo vòng lặp include chéo nhau — 2 launch file include lẫn nhau (trực tiếp hoặc gián tiếp qua file thứ 3) gây lỗi đệ quy vô hạn lúc parse — giữ cấu trúc include theo 1 chiều rõ ràng (launch file gốc include launch file con, không ngược lại).

Kết luận

Launch file là công cụ bắt buộc phải thành thạo khi hệ thống robot vượt quá vài node — cho phép khởi động, cấu hình tham số, và lắp ráp nhiều launch file con thành 1 hệ thống hoàn chỉnh chỉ bằng 1 lệnh. Kiến trúc phân tầng (launch gốc include launch con) là cách tổ chức chuẩn cho dự án AMR thực tế có nhiều thành phần độc lập. Bài tiếp theo trong chuyên mục, cũng là bài cuối, nói về Parameter — cách truyền cấu hình runtime cho từng node mà launch file vừa học thường dùng để thiết lập.

Launch File trong ROS2 — khởi động nhiều node cùng lúc — Atlasbot