Atlas Robotics
AMR Software ArchitectureTrung bình

Driver Layer: giao thức nói chuyện giữa firmware và ROS2

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

Driver Layer: giao thức nói chuyện giữa firmware và ROS2
Driver layer là lớp phiên dịch giữa giao thức firmware và ROS2 topics

Bài Bức tranh toàn cảnh phần mềm robot đặt "Giao tiếp" là lớp nằm giữa Firmware và ROS2. Đây chính là Driver Layer — không phải driver động cơ (đã nói ở bài Motor Driver), mà là driver phần mềm: đoạn code chạy trên máy tính chính (ROS2), đóng vai trò phiên dịch giữa giao thức riêng của firmware và hệ sinh thái topic/message chuẩn của ROS2.

Khái niệm chính

Firmware (chạy trên MCU) và ROS2 (chạy trên SBC) là hai thế giới hoàn toàn khác nhau — MCU không biết gì về DDS, topic, hay message type của ROS2; nó chỉ biết đọc/ghi byte qua UART. Driver layer đứng giữa, làm đúng một việc: dịch đúng, dịch đủ nhanh giữa hai định dạng dữ liệu khác nhau, không chứa logic điều khiển (đó là việc của Nav2/PID đã học ở bài Motor Control).

Nguyên lý hoạt động

Chiều lên (firmware → ROS2):
    đọc dữ liệu thô qua Serial (ví dụ "e 1523 1489")
    → parse thành số → đóng gói thành message chuẩn (EncoderVals)
    → publish lên topic ROS2

Chiều xuống (ROS2 → firmware):
    subscribe /cmd_vel (message Twist chuẩn ROS2)
    → tính toán ra lệnh PWM cho từng bánh
    → đóng gói thành chuỗi lệnh text đơn giản (ví dụ "o 100 100")
    → gửi qua Serial xuống firmware

Đây đúng là kiến trúc đã dùng trong dự án Diff Robot (phần showcase của trang này): package diff_serial_bridge đọc/ghi qua Serial UART 57600 baud bằng một tập lệnh text đơn giản, dễ debug trực tiếp qua terminal.

Một chi tiết thiết kế đáng chú ý (cũng từ dự án Diff Robot): thay vì dùng thẳng kiểu dữ liệu ROS2 có sẵn cho dữ liệu encoder/lệnh động cơ, dự án định nghĩa message type riêng (MotorCommand, EncoderVals, MotorVels trong package diff_serial_mgs) — giúp giao diện giữa driver layer và các node khác rõ ràng đúng ngữ nghĩa, dễ mở rộng thêm field mà không phá vỡ code đang dùng kiểu dữ liệu chuẩn ở chỗ khác trong hệ thống.

Tóm lại: Trộn lẫn logic điều khiển vào lớp này (ví dụ tự ý làm mượt tốc độ trong driver thay vì để tầng trên quyết định) là một lỗi kiến trúc phổ biến, khiến hệ thống khó debug vì logic bị phân tán không rõ ràng.

Kiến thức kỹ thuật

Công thức

Thời gian truyền một message qua Serial phụ thuộc trực tiếp vào baud rate và số byte cần gửi — yếu tố quyết định giao thức text hay binary phù hợp hơn ở tần số giao tiếp mong muốn:

Thời_gian_truyền ≈ (Số_bit_message) / Baud_rate

VD message text "e 1523 1489\n" (13 ký tự ≈ 130 bit với start/stop bit):
Ở 57600 baud: 130 / 57600 ≈ 2.3ms

VD message binary tương đương (2 số int16 + header + checksum ≈ 6 byte = 60 bit):
Ở 57600 baud: 60 / 57600 ≈ 1ms

Ở tần số gửi 50Hz (chu kỳ 20ms), cả 2 giao thức đều có nhiều dư địa thời gian —
chênh lệch chỉ trở nên đáng kể khi tần số giao tiếp tăng lên vài trăm Hz

Thông số

Giao thức textGiao thức binary
Dễ debugRất dễ — mở terminal serial, gõ tay lệnh, đọc được ngayKhó — cần công cụ giải mã riêng
Băng thôngTốn hơn (mỗi số là nhiều byte ASCII)Tiết kiệm hơn (mỗi số vài byte cố định)
Tốc độ parseChậm hơn (phải parse chuỗi)Nhanh hơn (đọc trực tiếp cấu trúc byte)
Phù hợpRobot nhỏ, tần số giao tiếp vừa phải (dưới ~100Hz)Robot cần băng thông cao, nhiều cảm biến tần số lớn

Ứng dụng thực tế

Với phần lớn AMR cỡ nhỏ/vừa, giao thức text đơn giản là lựa chọn hợp lý — khả năng debug trực tiếp bằng cách gõ lệnh tay qua terminal serial trong lúc phát triển giá trị hơn nhiều so với vài phần trăm băng thông tiết kiệm được từ giao thức binary, trừ khi robot thực sự cần truyền lượng dữ liệu lớn (ví dụ ảnh camera) qua đúng kênh Serial đó — như tính ở mục Công thức, chênh lệch thời gian truyền giữa 2 giao thức chỉ thực sự đáng kể khi tần số giao tiếp vượt xa mức 50-100Hz thông thường của dữ liệu encoder/lệnh động cơ.

Ví dụ thực tế

def thoi_gian_truyen(so_bit, baud_rate):
    return so_bit / baud_rate * 1000  # ms

baud = 57600

# Text: "e 1523 1489\n" ~ 13 ky tu, moi ky tu ~10 bit (start+8data+stop)
t_text = thoi_gian_truyen(13 * 10, baud)

# Binary: header(1) + 2x int16(4) + checksum(1) = 6 byte = 48 bit + framing overhead
t_binary = thoi_gian_truyen(60, baud)

print(f"Text protocol: {t_text:.2f} ms/message")
print(f"Binary protocol: {t_binary:.2f} ms/message")
print(f"So voi chu ky 20ms (50Hz): text con du {20-t_text:.1f}ms, binary con du {20-t_binary:.1f}ms")
Output:
Text protocol: 2.26 ms/message
Binary protocol: 1.04 ms/message
So voi chu ky 20ms (50Hz): text con du 17.7ms, binary con du 19.0ms

Cả 2 giao thức đều dư thời gian rất nhiều so với chu kỳ 50Hz — minh chứng bằng số cho việc chọn giao thức text vì dễ debug không đánh đổi đáng kể về tốc độ ở tần số giao tiếp thông thường của AMR cỡ nhỏ-vừa.

Lỗi thường gặp

  • Nhét logic điều khiển vào driver layer — như đã nêu ở phần Tóm lại, driver chỉ nên dịch dữ liệu, không nên tự ý làm mượt tốc độ hay ra quyết định thay tầng điều khiển phía trên.
  • Không có cơ chế phát hiện mất gói/timeout — Serial không đảm bảo dữ liệu tới đúng lúc, đúng thứ tự trong mọi trường hợp — nhiễu điện, cáp lỏng, hoặc buffer đầy có thể làm mất hoặc trễ gói dữ liệu; thiếu timeout/checksum khiến odometry lệch vĩnh viễn mà không có cách nào tự phát hiện.
  • Dùng thẳng kiểu dữ liệu ROS2 chuẩn generic thay vì message type riêng có ngữ nghĩa rõ ràng — khiến code khó đọc hơn (phải đoán field nào chứa gì) và khó mở rộng thêm dữ liệu mới mà không phá vỡ chỗ khác đang dùng cùng kiểu dữ liệu đó.
  • Đọc Serial theo kiểu blocking trên cùng luồng xử lý chính — nếu việc đọc dữ liệu Serial chặn (block) luồng chính chờ dữ liệu tới, toàn bộ node driver có thể bị treo khi kết nối Serial gặp sự cố, ảnh hưởng dây chuyền tới các node khác phụ thuộc dữ liệu từ nó.

Kết luận

Driver Layer là lớp mỏng nhưng dễ bị lạm dụng nhất trong toàn bộ kiến trúc phần mềm AMR — kỷ luật giữ nó chỉ làm đúng một việc (dịch dữ liệu, không ra quyết định) giúp hệ thống dễ debug hơn rất nhiều khi có sự cố. Bài tiếp theo trong chuyên mục đi vào ROS2 Layer — tầng hạ tầng giao tiếp mà driver layer vừa học cách "nói chuyện" cùng.

Driver Layer: giao thức nói chuyện giữa firmware và ROS2 — Atlasbot