Python bình thường hóa quaternion

Vui lòng hỏi về các vấn đề và câu hỏi liên quan đến hướng dẫn này về câu trả lời. hoa hồng. tổ chức. Đừng quên đưa vào câu hỏi của bạn liên kết đến trang này, các phiên bản HĐH & ROS của bạn, đồng thời thêm các thẻ thích hợp

Sự mô tả. Khái niệm cơ bản về cách sử dụng quaternion trong ROS

từ khóa. tứ phương, phép quay

Cấp hướng dẫn. TRUNG GIAN

Các nguồn lực khác

Có một hướng dẫn tuyệt vời ở đây

Các thành phần của một quaternion

ROS sử dụng quaternion để theo dõi và áp dụng phép quay. Một quaternion có 4 thành phần (x,y,z,w). Đúng vậy, 'w' là cuối cùng (nhưng hãy cẩn thận. một số thư viện như Eigen đặt w làm số đầu tiên. ). Bậc bốn đơn vị thường được sử dụng không tạo ra chuyển động quay quanh các trục x/y/z là (0,0,0,1)

(C++)

Độ lớn của một quaternion phải là một. Nếu các lỗi số gây ra cường độ bậc bốn khác với một, ROS sẽ in các cảnh báo. Để tránh những cảnh báo này, hãy chuẩn hóa quaternion

ROS sử dụng hai kiểu dữ liệu quaternion. tin nhắn và 'tf. ' Để chuyển đổi giữa chúng trong C++, hãy sử dụng các phương thức của tf2_geometry_msgs

(C++)

(Trăn)

Suy nghĩ bằng RPY sau đó chuyển đổi sang quaternion

Thật dễ dàng để con người nghĩ về các phép quay quanh các trục nhưng khó nghĩ về các bậc bốn. Một gợi ý là tính toán các góc quay của mục tiêu theo (cuộn quanh trục X)/(độ dốc tiếp theo quanh trục Y)/(độ lệch tiếp theo quanh trục Z), sau đó chuyển đổi thành bậc bốn

(Trăn)

Áp dụng phép quay quaternion

Để áp dụng phép quay của một bậc bốn cho một tư thế, chỉ cần nhân bậc bốn trước đó của tư thế với bậc bốn đại diện cho góc quay mong muốn. Thứ tự của phép nhân này quan trọng

(C++)

(Trăn)

   1 from tf.transformations import *
   2 
   3 q_orig = quaternion_from_euler(0, 0, 0)
   4 q_rot = quaternion_from_euler(pi, 0, 0)
   5 q_new = quaternion_multiply(q_rot, q_orig)
   6 print q_new

Đảo ngược một quaternion

Một cách dễ dàng để đảo ngược một quaternion là phủ định thành phần w

(Trăn)

phép quay tương đối

Giả sử bạn có hai bậc bốn từ cùng một khung, q_1 và q_2. Bạn muốn tìm phép quay tương đối, q_r, để đi từ q_1 đến q_2

Bạn có thể giải q r tương tự như giải phương trình ma trận. Đảo ngược q_1 và nhân phải cả hai vế. Một lần nữa, thứ tự phép nhân là quan trọng

Đây là một ví dụ để có được góc quay tương đối từ tư thế rô-bốt trước đó sang tư thế rô-bốt hiện tại

NormalizedQuaternionNormalizedQuaternionNormalizedQuaternionNormalizedQuaternionnormalizedQuaternionnormalized_quaternion (kiểm soát đầu ra)  bậc bốn HQuaternion, HTupleSequence[float]HTupleHtuple (thực) (gấp đôi) (gấp đôi) (gấp đôi)

Trừ khi tôi hoàn toàn nhầm lẫn, tốt hơn hết là không nên bảo toàn góc khi chuẩn hóa để giải quyết các lỗi làm tròn (trong bối cảnh sử dụng bậc bốn để biểu thị các phép quay, đặc biệt là trong các trò chơi). Hãy để tôi giải thích tại sao

giả sử bạn có hai bậc bốn (tôi sẽ gọi chúng là

Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
0 và
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
1 từ đây trở đi) được cho là đại diện cho các phép quay, nhưng không phải là đơn vị do lỗi làm tròn và bạn muốn nhân chúng (tôi sẽ gọi . Chúng tôi cũng muốn đây là một bậc bốn đơn vị). Giả sử
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
3 là một biến, khi nhân với mọi thành phần của
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
0,
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
0 trở thành một bậc bốn đơn vị (có nghĩa là
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
3 là một chia cho độ dài euclide của
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
0, nhưng điều đó thực sự không liên quan ở đây.
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
1 làm điều tương tự cho
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
1. Nếu bây giờ chúng ta nhân các bậc bốn sau khi chuẩn hóa (tức là
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
3), chúng ta sẽ nhận được kết quả sau

Q3.w = t1*Q1.w*t2*Q2.w - t1*Q1.x*t2*Q2.x - t1*Q1.y*t2*Q2.y - t1*Q1.z*t2*Q2.z
Q3.x = t1*Q1.w*t2*Q2.x + t1*Q1.x*t2*Q2.w + t1*Q1.y*t2*Q2.z - t1*Q1.z*t2*Q2.y
Q3.y = t1*Q1.w*t2*Q2.y - t1*Q1.x*t2*Q2.z + t1*Q1.y*t2*Q2.w + t1*Q1.z*t2*Q2.x
Q3.z = t1*Q1.w*t2*Q2.z + t1*Q1.x*t2*Q2.y - t1*Q1.y*t2*Q2.x + t1*Q1.z*t2*Q2.w

mà có thể được viết lại như

Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)

nói cách khác,

Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
4. Như bạn có thể thấy, chuẩn hóa theo cách này sau phép nhân dẫn đến cùng một bậc bốn như chuẩn hóa cả hai đầu vào trước khi nhân. Điều này có nghĩa là chúng ta chỉ phải chuẩn hóa ngay trước khi áp dụng phép quay cho một vectơ/lưới/điểm, thay vì sau mỗi phép tính, vì nó tạo ra cùng một kết quả bất kể bậc bốn trôi bao xa so với đơn vị

Bây giờ, hãy xem phép tính tương tự, nhưng với cách bảo toàn góc để tạo đơn vị bậc bốn (biến

Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
5 hiện tạo đơn vị bậc bốn khi được nhân với chỉ các phần không thực (còn gọi là xyz))

Q3.w = Q1.w*Q2.w - t1*Q1.x*t2*Q2.x - t1*Q1.y*t2*Q2.y - t1*Q1.z*t2*Q2.z
Q3.x = Q1.w*Q2.x + t1*Q1.x*Q2.w + t1*Q1.y*t2*Q2.z - t1*Q1.z*t2*Q2.y
Q3.y = Q1.w*Q2.y - t1*Q1.x*t2*Q2.z + t1*Q1.y*Q2.w + t1*Q1.z*t2*Q2.x
Q3.z = Q1.w*Q2.z + t1*Q1.x*t2*Q2.y - t1*Q1.y*t2*Q2.x + t1*Q1.z*Q2.w

lưu ý cách các thành phần không có thực của

Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
2 không còn có nhân tử chung nữa. Điều này có nghĩa là việc chuẩn hóa
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
2 sau phép toán theo cách này có thể dẫn đến một bậc bốn khác với cái mà bạn sẽ nhận được nếu bạn chuẩn hóa
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
1 và
Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)
0 theo cách này trước phép toán

Bình thường hóa một quaternion không phải là một hoạt động rẻ tiền, vì vậy, tốt hơn là sử dụng cách không bảo toàn góc cho những nội dung như trò chơi, vì bạn cần sử dụng nó ít thường xuyên hơn, đặc biệt là khi tổng hợp một số lượng lớn các phép quay. Tôi không chắc liệu điều tương tự có đúng với các hoạt động bậc bốn khác hay không, nhưng xem xét bạn có thể sẽ nhân các bậc bốn rất nhiều, ít nhất theo ý kiến ​​​​của tôi, nên sử dụng cách không bảo toàn góc