Hệ toạ độ trong Robot: vì sao một robot cần nhiều hệ toạ độ cùng lúc
Atlasbot · 17/8/2026 · 10 phút đọc
Một điểm LiDAR phát hiện được ở toạ độ (2, 0.5) — nhưng 2 mét theo hướng nào, tính từ đâu? Câu hỏi này chỉ có nghĩa khi gắn với một hệ toạ độ (coordinate frame) cụ thể. Robot thực tế không dùng một hệ toạ độ duy nhất — luôn cần ít nhất 3-4 hệ khác nhau, mỗi hệ trả lời đúng một câu hỏi.
Khái niệm chính
Bốn hệ toạ độ phổ biến trong robot di động:
base_link— gắn chết vào thân robot, gốc toạ độ thường đặt tại tâm robot, trục x hướng về phía trước. Toạ độ một cảm biến gắn cứng trên robot luôn cố định trong hệ này — không đổi dù robot di chuyển đi đâuodom— hệ toạ độ "cục bộ", gốc đặt tại vị trí robot lúc khởi động, cập nhật liên tục theo odometry. Mượt, cập nhật tần số cao, nhưng trôi dần theo thời gian vì sai số tích luỹmap— hệ toạ độ "tuyệt đối" so với bản đồ đã biết, được hiệu chỉnh định kỳ bằng SLAM/AMCL để triệt tiêu sai số trôi củaodom. Không mượt bằngodomnhưng chính xác dài hạn hơnsensor_frame(ví dụlidar_link,camera_link) — gắn tại đúng vị trí vật lý của từng cảm biến
Tóm lại: Câu hỏi "toạ độ này là bao nhiêu?" luôn phải đi kèm câu hỏi thứ hai "so với hệ toạ độ nào?" — bỏ qua vế thứ hai là nguồn gốc của phần lớn lỗi robot "chạy sai vị trí" dù công thức tính toán hoàn toàn đúng.
Nguyên lý hoạt động
Mỗi hệ phục vụ một nhu cầu khác nhau, đánh đổi giữa "mượt" và "chính xác dài hạn":
base_link → cố định so với robot, dùng để biết cảm biến gắn ở đâu
odom → mượt, tần số cao, dùng cho điều khiển tức thời — nhưng trôi dần
map → chính xác dài hạn, dùng cho lập kế hoạch đường đi toàn cục — cập nhật chậm hơn
Nếu chỉ dùng map cho mọi thứ, robot sẽ "giật" mỗi khi AMCL hiệu chỉnh lại vị trí. Nếu chỉ dùng odom, vị trí sẽ trôi dần không giới hạn theo thời gian. Tách hai hệ riêng cho phép mỗi bộ điều khiển dùng đúng loại dữ liệu phù hợp với tần số/độ chính xác nó cần.
Biết toạ độ một điểm trong hệ này, muốn biết toạ độ tương ứng trong hệ khác — cần một phép transform nối hai hệ lại. Chuỗi các phép transform nối tiếp nhau tạo thành TF tree — mỗi hệ toạ độ là một node, mỗi cạnh nối hai node là một transform.
Kiến thức kỹ thuật
Thông số
Chuẩn định hướng trục toạ độ mà ROS2 quy định thống nhất (REP-103) — tuân theo đúng chuẩn này giúp mọi package (Nav2, SLAM, driver cảm biến) "hiểu nhau" mà không cần tự quy đổi:
| Trục | Hướng quy ước |
|---|---|
| x | Hướng về phía trước robot |
| y | Hướng sang trái robot |
| z | Hướng lên trên |
| Đơn vị khoảng cách | Mét (m) |
| Đơn vị góc | Radian (rad) |
Đây là hệ toạ độ tay phải (right-handed) — quy tắc bàn tay phải xác định chiều dương của phép xoay quanh mỗi trục.
Ứng dụng thực tế
Khi vận hành nhiều robot AMR trong cùng 1 khu vực (fleet), mỗi robot có hệ odom riêng của chính nó (gốc đặt tại vị trí robot đó lúc khởi động) — hệ odom của robot A hoàn toàn không có ý nghĩa gì với robot B. Để các robot biết vị trí tương đối của nhau (tránh va chạm, điều phối nhiệm vụ), cần 1 hệ toạ độ map (hoặc một hệ world chung cấp cao hơn) mà mọi robot cùng tham chiếu tới — đây là lý do hệ thống quản lý fleet luôn cần một bước hiệu chỉnh (localization) đưa vị trí ước lượng của từng robot về cùng 1 hệ toạ độ chung trước khi so sánh hay điều phối giữa các robot.
Ví dụ thực tế
import numpy as np
# Robot đang ở vị trí (2, 1) trong hệ map, xoay 90 độ so với hệ map
robot_x, robot_y, robot_theta = 2, 1, np.radians(90)
# Một điểm LiDAR đo được cách robot 1m về phía trước, trong hệ base_link
point_local = np.array([1, 0])
# Xoay theo hướng robot rồi dịch theo vị trí robot — chuyển sang hệ map
R = np.array([[np.cos(robot_theta), -np.sin(robot_theta)],
[np.sin(robot_theta), np.cos(robot_theta)]])
point_map = R @ point_local + np.array([robot_x, robot_y])
print(f"Diem trong he map: ({point_map[0]:.2f}, {point_map[1]:.2f})")
Output:
Diem trong he map: (2.00, 2.00)
Điểm "cách robot 1m phía trước" trong hệ base_link trở thành (2, 2) trong hệ map — vì robot đang xoay 90° (nhìn theo trục y của hệ map), nên "phía trước robot" tương ứng với "+y trong hệ map", cộng với vị trí gốc robot (2, 1) cho ra kết quả này.
Lỗi thường gặp
- Dùng toạ độ mà không xác định rõ đang ở hệ nào — cộng/so sánh trực tiếp toạ độ từ 2 hệ khác nhau (VD: vị trí đích trong hệ
mapvới vị trí robot trong hệodom) mà không transform trước — lỗi rất phổ biến và khó phát hiện vì code vẫn chạy, chỉ cho kết quả sai. - Coi
odomlà chính xác tuyệt đối trong thời gian dài — sai số trôi tích luỹ dần, sau vài phút di chuyển liên tục có thể lệch hàng chục cm tới vài mét tuỳ chất lượng encoder/IMU — chỉmap(đã hiệu chỉnh bằng SLAM/AMCL) mới đáng tin cho quyết định dài hạn. - Driver cảm biến bên thứ ba dùng quy ước trục khác REP-103 — một số camera/IMU gốc dùng z-forward (hướng ống kính) thay vì x-forward theo chuẩn ROS — tích hợp mà không quy đổi đúng gây lệch hướng dữ liệu âm thầm, dữ liệu "đúng số" nhưng sai ý nghĩa hình học.
- Tin vào
frame_idghi trong message mà không thực sự transform — message ROS2 luôn có trườngframe_idkhai nó thuộc hệ nào, nhưng chỉ đọc nhãn này không tự động chuyển đổi toạ độ — vẫn phải gọitf2để tra cứu và áp dụng transform thực sự trước khi dùng toạ độ ở hệ khác.
Kết luận
Một robot cần nhiều hệ toạ độ cùng lúc vì mỗi hệ đánh đổi giữa độ mượt và độ chính xác dài hạn khác nhau — base_link cho vị trí tương đối cố định, odom cho điều khiển tức thời, map cho quyết định toàn cục. Luôn xác định rõ hệ toạ độ trước khi thao tác trên bất kỳ con số toạ độ nào. Bài tiếp theo trong chuyên mục nói về Rotation — cách biểu diễn phép xoay chi tiết hơn ma trận xoay 2D đã thấy ở bài Matrix, mở rộng sang không gian 3D.