Bức tranh toàn cảnh phần mềm robot: từ firmware đến ROS2, SLAM, Nav2
Atlasbot · 12/7/2026 · 11 phút đọc
Bài Kiến trúc AMR ở chuyên mục Tổng quan AMR/AGV đã giới thiệu mô hình 5 tầng: Hardware, Driver, ROS2, Navigation+Localization, Application. Bài này mở đầu chuyên mục AMR Software Architecture — nơi mỗi tầng đó được tách thành một bài riêng, đi sâu hơn nhiều so với bức tranh tổng quan ban đầu.
Khái niệm chính
Một AMR hoàn chỉnh phải giải quyết đồng thời hai loại bài toán có bản chất đối lập nhau:
- Thời gian thực, đơn giản — quay động cơ đúng tốc độ, đọc encoder không bỏ sót xung — cần độ trễ thấp, xác định (deterministic)
- Phức tạp, không cần thời gian thực tuyệt đối — hiểu bản đồ, tính đường đi tối ưu, tránh vật cản động — cần sức mạnh tính toán lớn, chấp nhận độ trễ vài chục–vài trăm mili-giây
Không có nền tảng phần cứng nào giỏi cả hai việc cùng lúc — đây chính là lý do bắt buộc phải chia thành các lớp riêng biệt, mỗi lớp chạy trên phần cứng phù hợp và chỉ giao tiếp với lớp liền kề qua một giao diện rõ ràng.
Nguyên lý hoạt động
Dữ liệu chảy theo hai chiều ngược nhau qua toàn bộ chồng lớp — không phải một đường ống một chiều: dữ liệu cảm biến chảy từ dưới lên (phần cứng → firmware → ROS2 → SLAM/Nav2), còn lệnh điều khiển chảy từ trên xuống (Nav2 → ROS2 → giao tiếp → firmware → driver động cơ). Vòng lặp Sense-Think-Act xét trên toàn hệ thống chính là vòng lặp dữ liệu đi lên rồi lệnh điều khiển đi xuống liên tục qua tất cả các lớp này — đúng công thức độ trễ tích luỹ đã tính ở bài Kiến trúc AMR.
Các bài tiếp theo trong chuyên mục này đi sâu vào từng tầng theo đúng thứ tự từ dưới lên: Hardware Layer, Driver Layer (đã có riêng), ROS2 Layer, Localization, Navigation, và Application.
Kiến thức kỹ thuật
Công thức
Ngân sách độ trễ (latency budget) cho phép mỗi tầng bao nhiêu thời gian xử lý cộng dồn tuỳ vào yêu cầu tần số phản ứng tổng thể — mở rộng trực tiếp từ công thức độ trễ tổng đã học ở bài Kiến trúc AMR:
Nếu hệ thống cần phản ứng trong tối đa 100ms (yêu cầu an toàn),
và đã biết Δt_Hardware ≈ 20ms (phản hồi vật lý động cơ, không đổi được nhiều)
Ngân sách còn lại cho phần mềm = 100 − 20 = 80ms,
chia cho 4 tầng phần mềm còn lại (Driver, ROS2, Navigation, Application)
→ mỗi tầng trung bình không nên vượt quá ~20ms xử lý
Đây là cách tư duy ngược — thay vì thiết kế từng tầng độc lập rồi cộng lại xem tổng bao nhiêu, xác định trước ngân sách độ trễ tổng cần đạt, rồi phân bổ ngược cho từng tầng.
Thông số
| Tầng | Ưu tiên thiết kế | Vấn đề thường gặp nếu vi phạm |
|---|---|---|
| Hardware/Driver (MCU) | Độ trễ thấp, xác định | Vòng an toàn phản ứng chậm |
| ROS2/Navigation (MPU) | Sức mạnh tính toán, độ chính xác | Tốn tài nguyên nếu chạy nhầm trên MCU |
| Application | Trải nghiệm người dùng, logic nghiệp vụ | Không ảnh hưởng an toàn nếu tách đúng lớp |
Ứng dụng thực tế
Một sai lầm phổ biến của người mới là nhảy thẳng vào học ROS2/SLAM mà bỏ qua các lớp bên dưới. Hậu quả thực tế: khi robot chạy sai, không biết lỗi nằm ở thuật toán SLAM hay ở việc encoder gắn lệch khiến dữ liệu odometry sai ngay từ đầu (đúng vấn đề đã học ở bài Odometry cho AMR) — debug mất nhiều thời gian hơn hẳn vì không biết nên kiểm tra lớp nào trước. Nắm chắc từng lớp theo đúng thứ tự — phần cứng, driver, rồi mới tới ROS2/Navigation — giúp debug đúng lớp ngay từ đầu, thay vì đoán mò từ lớp cao nhất xuống.
Ví dụ thực tế
Triệu chứng: robot Nav2 báo "path planning thành công" nhưng robot
đi lệch quỹ đạo rõ rệt so với đường đã tính
Debug đúng thứ tự từ dưới lên (không đoán mò từ Nav2 xuống):
1. Kiểm tra Hardware: bánh xe có mòn không đều, đường kính hiệu dụng đúng không?
2. Kiểm tra Driver: encoder đọc đúng chưa, hằng số khoảng_cách_mỗi_tick đúng chưa?
3. Kiểm tra ROS2: /odom publish đúng tần số, đúng frame chưa?
4. Kiểm tra Navigation: AMCL có hội tụ đúng vị trí thực tế không?
→ Trong đa số trường hợp thực tế, nguyên nhân nằm ở bước 1-2 (sai số phần cứng/
driver tích luỹ), không phải ở thuật toán Nav2 — nhưng người mới thường
nghi ngờ Nav2 trước tiên vì đó là nơi "thấy" hành vi sai lệch rõ nhất
Lỗi thường gặp
- Bắt đầu học/debug từ tầng cao nhất (Application, Navigation) thay vì từ dưới lên — như ví dụ trên, phần lớn lỗi thực tế bắt nguồn từ phần cứng/driver, dù triệu chứng biểu hiện rõ nhất ở tầng cao.
- Không phân bổ ngân sách độ trễ rõ ràng cho từng tầng khi thiết kế — thiết kế từng tầng độc lập rồi mới phát hiện tổng độ trễ vượt yêu cầu an toàn, thay vì tính ngược từ ngân sách tổng như ở mục Công thức.
- Đặt xử lý nặng tính toán trên MCU vì "tiện" — vi phạm nguyên tắc phân lớp theo phần cứng phù hợp, khiến vòng điều khiển thời gian thực bị chậm lại bởi tác vụ không cần thời gian thực.
- Bỏ qua việc học/kiểm tra từng tầng con bên dưới trước khi lên ROS2/SLAM — dẫn tới hiểu sai nguyên nhân lỗi, tốn thời gian sửa sai chỗ khi vấn đề thực sự nằm ở tầng khác.
Kết luận
Chia lớp không phải một lựa chọn thiết kế tuỳ ý — nó là giải pháp bắt buộc cho việc một hệ thống phải vừa đáp ứng thời gian thực vừa đủ sức mạnh tính toán cho các thuật toán phức tạp. Học và debug theo đúng thứ tự từ dưới lên, cùng với việc phân bổ ngân sách độ trễ rõ ràng cho từng tầng, là kỷ luật kỹ thuật giúp tránh phần lớn thời gian debug lãng phí. Bài tiếp theo trong chuyên mục đi sâu vào Hardware Layer — tầng thấp nhất, nơi mọi dữ liệu bắt đầu.