Rotation và Euler Angles: xoay robot trong không gian 3D
Atlasbot · 17/8/2026 · 10 phút đọc
Robot di động 2D (mọi robot trong showcase dự án của trang này) chỉ cần một con số duy nhất để biết đang "nhìn" hướng nào: góc heading θ. Nhưng ngay khi có IMU đo cả 3 trục, hoặc robot có tay máy/gắn camera xoay được nhiều bậc tự do, một góc thôi không đủ — cần biểu diễn hướng trong không gian 3D đầy đủ. Cách trực quan nhất là Euler angles.
Khái niệm chính
Roll, Pitch, Yaw — ba góc xoay quanh ba trục:
Roll (φ) — xoay quanh trục x (trước-sau) — robot "nghiêng" trái/phải
Pitch (θ) — xoay quanh trục y (trái-phải) — robot "cúi/ngẩng" đầu
Yaw (ψ) — xoay quanh trục z (lên-xuống) — robot "quay" trái/phải — chính là θ trong robot 2D
Với robot di động chạy trên mặt phẳng, Roll và Pitch gần như luôn xấp xỉ 0 (trừ khi đi qua dốc/gồ ghề) — chỉ Yaw thay đổi liên tục, đây là lý do robot 2D chỉ cần theo dõi một góc duy nhất. IMU là cảm biến đo trực tiếp cả ba góc này.
Nguyên lý hoạt động
Euler angles dễ hình dung nhưng có một nhược điểm nghiêm trọng: khi một trong ba góc (thường là Pitch) tiến gần 90°, hai trục xoay còn lại trở nên trùng nhau về mặt hiệu ứng — mất đi một bậc tự do xoay. Hiện tượng này gọi là gimbal lock.
Pitch = 90° → trục xoay Roll và Yaw hiệu ứng trùng nhau
→ không còn cách nào xoay riêng biệt theo 2 trục đó nữa
Về mặt toán học, một số tổ hợp góc gây ra tính toán không ổn định khi chuyển đổi qua lại giữa Euler angles và các dạng biểu diễn khác — robot bay (drone) với chuyển động lật ngửa/cúi gập mạnh là trường hợp dễ gặp gimbal lock nhất trong thực tế.
Tóm lại: Gimbal lock không phải lỗi cảm biến hay lỗi code — nó là hạn chế cố hữu về mặt toán học của cách biểu diễn Euler angles. Cách duy nhất né được hoàn toàn là đổi sang một cách biểu diễn khác không có điểm kỳ dị (singularity) này — chính là Quaternion (bài tiếp theo).
Kiến thức kỹ thuật
Công thức
Mỗi góc Euler tương ứng một ma trận xoay quanh đúng một trục (mở rộng công thức ma trận xoay 2D đã học ở bài Matrix); nhân ba ma trận này theo đúng thứ tự cho ra ma trận xoay tổng hợp:
R = R_z(yaw) × R_y(pitch) × R_x(roll)
Thứ tự nhân quan trọng — vì phép nhân matrix không giao hoán, xoay theo thứ tự Yaw→Pitch→Roll cho kết quả khác với Roll→Pitch→Yaw dù cùng ba góc số.
Thông số
Các quy ước thứ tự Euler angles khác nhau giữa các lĩnh vực/thư viện — nguồn gốc phổ biến nhất của lỗi "góc đúng số nhưng sai hướng" khi ghép dữ liệu từ nhiều nguồn:
| Quy ước | Thứ tự áp dụng | Hay dùng trong |
|---|---|---|
| ZYX (Yaw-Pitch-Roll) | Yaw trước, Roll cuối | Hàng không, ROS/robotics phổ biến nhất |
| XYZ | Roll trước, Yaw cuối | Một số thư viện đồ hoạ 3D/game engine |
| Intrinsic vs Extrinsic | Xoay quanh trục đã xoay (intrinsic) hay trục cố định ban đầu (extrinsic) | Khác biệt tinh vi, luôn gây nhầm khi không đọc kỹ tài liệu |
Ứng dụng thực tế
Khi tích hợp một IMU từ hãng A (xuất dữ liệu Roll/Pitch/Yaw theo quy ước XYZ) vào một hệ thống điều khiển dùng thư viện của hãng B (kỳ vọng quy ước ZYX) mà không quy đổi đúng, dữ liệu hướng nhận được vẫn là 3 con số hợp lệ, chỉ sai ý nghĩa hình học — robot có thể tưởng đang nghiêng trong khi thực tế đang quay, gây điều khiển sai mà không có lỗi rõ ràng nào để debug. Đây là lý do khi tích hợp cảm biến hướng từ bên thứ ba, luôn phải xác nhận rõ quy ước thứ tự trục trong tài liệu trước khi ghép vào pipeline điều khiển, không giả định "chắc giống ROS".
Ví dụ thực tế
import numpy as np
def rotation_matrix_zyx(yaw, pitch, roll):
Rz = np.array([[np.cos(yaw), -np.sin(yaw), 0],
[np.sin(yaw), np.cos(yaw), 0],
[0, 0, 1]])
Ry = np.array([[np.cos(pitch), 0, np.sin(pitch)],
[0, 1, 0],
[-np.sin(pitch), 0, np.cos(pitch)]])
Rx = np.array([[1, 0, 0],
[0, np.cos(roll), -np.sin(roll)],
[0, np.sin(roll), np.cos(roll)]])
return Rz @ Ry @ Rx
# Minh hoạ gimbal lock: pitch = 90 độ
R1 = rotation_matrix_zyx(np.radians(30), np.radians(90), np.radians(0))
R2 = rotation_matrix_zyx(np.radians(0), np.radians(90), np.radians(30))
print("R1 == R2 (gimbal lock):", np.allclose(R1, R2))
Output:
R1 == R2 (gimbal lock): True
Hai tổ hợp góc hoàn toàn khác nhau (yaw=30°,roll=0° và yaw=0°,roll=30°) cho ra cùng một ma trận xoay khi pitch=90° — minh chứng trực quan cho gimbal lock: tại điểm kỳ dị này, thông tin về Roll và Yaw riêng biệt đã bị "hoà lẫn" vào nhau, không thể khôi phục lại chính xác từng góc gốc.
Lỗi thường gặp
- Nhầm quy ước thứ tự trục giữa các thư viện — như đã nói ở mục Ứng dụng thực tế, dữ liệu vẫn "đúng số" nhưng sai ý nghĩa hình học nếu không khớp quy ước, khó phát hiện qua kiểm tra thông thường.
- Điều khiển bất ổn gần điểm gimbal lock — hệ thống điều khiển dựa trực tiếp trên Euler angles có thể phản ứng bất thường/giật cục khi Pitch tiến gần 90°, do đạo hàm của các góc trở nên không ổn định gần điểm kỳ dị.
- Nội suy tuyến tính (linear interpolation) trực tiếp giữa 2 bộ Euler angles — cộng/trừ/chia trung bình các góc Euler một cách tuyến tính không cho ra đường xoay ngắn nhất/mượt nhất trong không gian 3D thực tế — đây chính là lý do Quaternion (bài tiếp theo) có phép nội suy riêng (SLERP) thiết kế đúng cho bài toán này.
- Trộn độ và radian — lỗi lặp lại xuyên suốt chuyên mục này, luôn kiểm tra đơn vị góc trước khi truyền vào hàm lượng giác.
Kết luận
Euler angles (Roll-Pitch-Yaw) trực quan và dễ hình dung nhưng mang theo 2 rủi ro cố hữu: gimbal lock tại các điểm kỳ dị, và sự mơ hồ về quy ước thứ tự trục giữa các thư viện/lĩnh vực khác nhau. Với robot 2D thuần tuý, chỉ cần theo dõi Yaw là đủ; với robot 3D đầy đủ (drone, tay máy), cần hiểu rõ hạn chế này trước khi chọn cách biểu diễn phù hợp. Bài tiếp theo trong chuyên mục nói về Quaternion — cách biểu diễn phép xoay không có gimbal lock, đánh đổi bằng việc khó hình dung trực quan hơn.