97 lines
2.8 KiB
Python
97 lines
2.8 KiB
Python
![]() |
# -- coding: utf-8 --
|
|||
|
import numpy as np
|
|||
|
from scipy.spatial.transform import Rotation as rot
|
|||
|
|
|||
|
import cv2
|
|||
|
import numpy as np
|
|||
|
import math
|
|||
|
|
|||
|
# 旋转矩阵转旋转向量(Rxyz->Rvector,按特定轴旋转)
|
|||
|
def rotvector2rot(rotvector):
|
|||
|
Rm = cv2.Rodrigues(rotvector)[0]
|
|||
|
return Rm
|
|||
|
|
|||
|
# 旋转矩阵转欧拉角
|
|||
|
def isRotationMatrix(R):
|
|||
|
Rt = np.transpose(R)
|
|||
|
shouldBeIdentity = np.dot(Rt, R)
|
|||
|
I = np.identity(3, dtype=R.dtype)
|
|||
|
n = np.linalg.norm(I - shouldBeIdentity)
|
|||
|
return n < 1e-6
|
|||
|
def rot2euler(R):
|
|||
|
# assert (isRotationMatrix(R))
|
|||
|
sy = math.sqrt(R[0, 0] * R[0, 0] + R[1, 0] * R[1, 0])
|
|||
|
singular = sy < 1e-6
|
|||
|
if not singular:
|
|||
|
x = math.atan2(R[2, 1], R[2, 2]) * 180 / np.pi
|
|||
|
y = math.atan2(-R[2, 0], sy) * 180 / np.pi
|
|||
|
z = math.atan2(R[1, 0], R[0, 0]) * 180 / np.pi
|
|||
|
else:
|
|||
|
x = math.atan2(-R[1, 2], R[1, 1]) * 180 / np.pi
|
|||
|
y = math.atan2(-R[2, 0], sy) * 180 / np.pi
|
|||
|
z = 0
|
|||
|
return np.array([x, y, z])
|
|||
|
def rot2eulerpi(R):
|
|||
|
# assert (isRotationMatrix(R))
|
|||
|
sy = math.sqrt(R[0, 0] * R[0, 0] + R[1, 0] * R[1, 0])
|
|||
|
singular = sy < 1e-6
|
|||
|
if not singular:
|
|||
|
x = math.atan2(R[2, 1], R[2, 2])
|
|||
|
y = math.atan2(-R[2, 0], sy)
|
|||
|
z = math.atan2(R[1, 0], R[0, 0])
|
|||
|
else:
|
|||
|
x = math.atan2(-R[1, 2], R[1, 1])
|
|||
|
y = math.atan2(-R[2, 0], sy)
|
|||
|
z = 0
|
|||
|
return np.array([x, y, z])
|
|||
|
def rot_to_ypr_zyx(R):
|
|||
|
"""
|
|||
|
将旋转矩阵R转换为Yaw-Pitch-Roll角度(Z-Y-X顺序)
|
|||
|
"""
|
|||
|
sin_p = 2 * (R[2, 0] ** 2 - R[0, 0] ** 2 + R[1, 0] ** 2) ** 0.5
|
|||
|
if sin_p < 1e-6:
|
|||
|
sin_p = 1e-6
|
|||
|
if R[2, 0] > 0:
|
|||
|
sin_p = -sin_p
|
|||
|
|
|||
|
roll = np.arctan2(R[2, 0], R[2, 2])
|
|||
|
pitch = np.arcsin(-R[2, 1])
|
|||
|
yaw = np.arctan2(R[1, 0], R[0, 0])
|
|||
|
|
|||
|
return yaw, pitch, roll
|
|||
|
def rot_to_ypr_xyz(R):
|
|||
|
# 计算R的trace值
|
|||
|
tr = np.trace(R)
|
|||
|
# 计算sqrt(R.T.R) - 1的模长,即平方根trace值
|
|||
|
sqrt_tr_m1 = np.sqrt(0.25 * ((tr - 3) ** 2) + (R[2, 2] - 1) ** 2)
|
|||
|
|
|||
|
# 根据平方根trace值判断Yaw-Pitch-Roll角的计算方法
|
|||
|
yaw = np.arctan2(R[2, 1], R[2, 2]) # 使用arctan2计算Yaw角
|
|||
|
pitch = np.arcsin(-R[2, 0]) # 使用arcsin计算Pitch角
|
|||
|
roll = np.arctan2(R[1, 0], R[0, 0]) # 使用arctan2计算Roll角
|
|||
|
|
|||
|
return yaw, pitch, roll
|
|||
|
|
|||
|
# 四元数转欧拉角
|
|||
|
def quaternion2euler(quaternion):
|
|||
|
r = rot.from_quat(quaternion)
|
|||
|
euler = r.as_euler('xyz', degrees=True)
|
|||
|
return euler
|
|||
|
|
|||
|
# 四元数转旋转矩阵
|
|||
|
def quaternion2rot(quaternion):
|
|||
|
r = rot.from_quat(quaternion)
|
|||
|
rot = r.as_matrix()
|
|||
|
return rot
|
|||
|
|
|||
|
# 欧拉角转四元数
|
|||
|
def euler2quaternion(euler):
|
|||
|
r = rot.from_euler('xyz', euler, degrees=True)
|
|||
|
quaternion = r.as_quat()
|
|||
|
return quaternion
|
|||
|
|
|||
|
# 欧拉角转旋转矩阵
|
|||
|
def euler2rot(euler):
|
|||
|
r = rot.from_euler('xyz', euler, degrees=True)
|
|||
|
rotation_matrix = r.as_matrix()
|
|||
|
return rotation_matrix
|