import open3d as o3d
import numpy as np
import copy
import mathdef create_coordinate_system(size=1.0, origin=[0, 0, 0]):
"""创建坐标系"""
coord = o3d.geometry.TriangleMesh.create_coordinate_frame(size=size, origin=origin)
return coord
def create_colored_cube(width=1.0, height=0.5, depth=0.3, color=[0.5, 0.5, 0.5]):
"""创建带颜色的立方体"""
cube = o3d.geometry.TriangleMesh.create_box(width=width, height=height, depth=depth)
cube.compute_vertex_normals()
cube.paint_uniform_color(color)
return cube
def get_rotation_matrix_x(angle):
"""绕X轴旋转矩阵"""
return np.array([
[1, 0, 0, 0],
[0, math.cos(angle), -math.sin(angle), 0],
[0, math.sin(angle), math.cos(angle), 0],
[0, 0, 0, 1]
])
def get_rotation_matrix_y(angle):
"""绕Y轴旋转矩阵"""
return np.array([
[math.cos(angle), 0, math.sin(angle), 0],
[0, 1, 0, 0],
[-math.sin(angle), 0, math.cos(angle), 0],
[0, 0, 0, 1]
])
def get_rotation_matrix_z(angle):
"""绕Z轴旋转矩阵"""
return np.array([
[math.cos(angle), -math.sin(angle), 0, 0],
[math.sin(angle), math.cos(angle), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
def get_translation_matrix(tx, ty, tz):
"""平移矩阵"""
return np.array([
[1, 0, 0, tx],
[0, 1, 0, ty],
[0, 0, 1, tz],
[0, 0, 0, 1]
])
def build_euler_transform_matrix(euler_angles, translation, order='xyz'):
"""
使用欧拉角构建变换矩阵
参数:
euler_angles: [rx, ry, rz] 欧拉角(弧度)
translation: [tx, ty, tz] 平移向量
order: 旋转顺序 ('xyz', 'zyx'等)
返回:
4x4变换矩阵
"""
rx, ry, rz = euler_angles
tx, ty, tz = translation
# 根据旋转顺序构建旋转矩阵
if order == 'xyz':
R_x = get_rotation_matrix_x(rx)
R_y = get_rotation_matrix_y(ry)
R_z = get_rotation_matrix_z(rz)
R = R_z @ R_y @ R_x # XYZ顺序: 先X, 再Y, 最后Z
elif order == 'zyx':
R_x = get_rotation_matrix_x(rx)
R_y = get_rotation_matrix_y(ry)
R_z = get_rotation_matrix_z(rz)
R = R_x @ R_y @ R_z # ZYX顺序: 先Z, 再Y, 最后X
else:
# 默认使用XYZ顺序
R_x = get_rotation_matrix_x(rx)
R_y = get_rotation_matrix_y(ry)
R_z = get_rotation_matrix_z(rz)
R = R_z @ R_y @ R_x
# 构建平移矩阵
T = get_translation_matrix(tx, ty, tz)
# 组合变换矩阵 (先旋转后平移)
transform_matrix = T @ R
return transform_matrix
def demonstrate_euler_transform():
"""
演示欧拉角变换矩阵与分步变换的对比
"""
print("=== 欧拉角变换矩阵与分步变换对比 ===")
# 创建原始物体和坐标系
original_cube = create_colored_cube(color=[0.8, 0.8, 0.8])
world_coord = create_coordinate_system(size=1.0)
# 定义变换参数
rotation_angle = math.pi / 2 # 90度
translation_distance = 2.0
# 分步变换 (你的代码)
cube_1 = copy.deepcopy(original_cube)
R_z = get_rotation_matrix_z(rotation_angle) # 绕世界Z轴旋转
R_x = get_rotation_matrix_x(rotation_angle) # 绕世界X轴旋转
R_y = get_rotation_matrix_y(rotation_angle) # 绕世界Y轴旋转
cube_1.transform(R_x)
cube_1.paint_uniform_color([0.5, 0, 0]) # 暗红色:X旋转后
cube_2 = copy.deepcopy(cube_1)
cube_2.transform(R_y)
cube_2.paint_uniform_color([0, 0.5, 0]) # 暗绿色:Y旋转后
cube_3 = copy.deepcopy(cube_2)
cube_3.transform(R_z)
cube_3.paint_uniform_color([0, 0, 0.5]) # 暗蓝色:Z旋转后
cube_4 = copy.deepcopy(cube_3)
T_x = get_translation_matrix(translation_distance, 0, 0) # 沿世界X轴平移
cube_4.transform(T_x)
cube_4.paint_uniform_color([0.5, 0.5, 0.5]) # 灰色:X平移后
cube_5 = copy.deepcopy(cube_4)
T_y = get_translation_matrix(0, translation_distance, 0) # 沿世界Y轴平移
cube_5.transform(T_y)
cube_5.paint_uniform_color([0.5, 0.2, 0.9]) # 紫色:最终结果
# 使用欧拉角构建变换矩阵
euler_angles = [rotation_angle, rotation_angle, rotation_angle] # [rx, ry, rz]
translation = [translation_distance, translation_distance, 0] # [tx, ty, tz]
# 构建变换矩阵 (注意:你的分步顺序是 X旋转 -> Y旋转 -> Z旋转 -> X平移 -> Y平移)
# 这对应于欧拉角顺序 XYZ 和 平移 [tx, ty, 0]
transform_matrix = build_euler_transform_matrix(euler_angles, translation, order='xyz')
# 应用变换矩阵
cube_matrix = copy.deepcopy(original_cube)
cube_matrix.transform(transform_matrix)
cube_matrix.paint_uniform_color([1, 1, 0]) # 黄色:矩阵变换结果
# 计算分步变换的等效矩阵
# 注意:你的分步顺序是 R_x -> R_y -> R_z -> T_x -> T_y
# 在左乘系统中,这对应于:T_y @ T_x @ R_z @ R_y @ R_x
step_by_step_matrix = T_y @ T_x @ R_z @ R_y @ R_x
# 应用分步等效矩阵
cube_step_matrix = copy.deepcopy(original_cube)
cube_step_matrix.transform(step_by_step_matrix)
cube_step_matrix.paint_uniform_color([0, 1, 1]) # 青色:分步等效矩阵结果
# 可视化
geometries = [
world_coord,
original_cube,
cube_1, cube_2, cube_3, cube_4, cube_5, # 分步变换
cube_matrix, # 欧拉角矩阵变换
cube_step_matrix # 分步等效矩阵
]
# 打印矩阵信息
print(f"欧拉角: {[math.degrees(a) for a in euler_angles]} 度")
print(f"平移: {translation}")
print(f"欧拉角变换矩阵:\n{transform_matrix}")
print(f"分步等效矩阵:\n{step_by_step_matrix}")
print(f"矩阵是否相等: {np.allclose(transform_matrix, step_by_step_matrix)}")
# 可视化
o3d.visualization.draw_geometries(
geometries,
window_name="欧拉角变换对比\n"
"灰色=原始, 暗红=X旋转, 暗绿=Y旋转, 暗蓝=Z旋转\n"
"灰色=X平移, 紫色=Y平移(最终), 黄色=欧拉角矩阵, 青色=分步等效矩阵",
width=1000, height=800
)
return transform_matrix, step_by_step_matrix
def demonstrate_different_euler_orders():
"""
演示不同欧拉角顺序的影响
"""
print("\n=== 不同欧拉角顺序对比 ===")
# 创建原始物体和坐标系
original_cube = create_colored_cube(color=[0.8, 0.8, 0.8])
world_coord = create_coordinate_system(size=1.0)
# 定义变换参数
euler_angles = [math.pi/4, math.pi/6, math.pi/3] # 45°, 30°, 60°
translation = [1.5, 1.0, 0]
# 不同欧拉角顺序的变换矩阵
T_xyz = build_euler_transform_matrix(euler_angles, translation, order='xyz')
T_zyx = build_euler_transform_matrix(euler_angles, translation, order='zyx')
T_xzy = build_euler_transform_matrix(euler_angles, translation, order='xzy')
# 应用变换
cube_xyz = copy.deepcopy(original_cube)
cube_xyz.transform(T_xyz)
cube_xyz.paint_uniform_color([1, 0, 0]) # 红色
cube_zyx = copy.deepcopy(original_cube)
cube_zyx.transform(T_zyx)
cube_zyx.paint_uniform_color([0, 1, 0]) # 绿色
cube_xzy = copy.deepcopy(original_cube)
cube_xzy.transform(T_xzy)
cube_xzy.paint_uniform_color([0, 0, 1]) # 蓝色
# 可视化
geometries = [world_coord, original_cube, cube_xyz, cube_zyx, cube_xzy]
print("不同欧拉角顺序对比:")
print(f"欧拉角: {[math.degrees(a) for a in euler_angles]} 度")
print(f"平移: {translation}")
print("红色=XYZ顺序, 绿色=ZYX顺序, 蓝色=XZY顺序")
o3d.visualization.draw_geometries(
geometries,
window_name="不同欧拉角顺序对比",
width=800, height=600
)
if __name__ == "__main__":
# 演示欧拉角变换矩阵与分步变换对比
transform_matrix, step_by_step_matrix = demonstrate_euler_transform()
print("\n" + "="*50)
print("关键要点总结:")
print("1. 欧拉角变换矩阵可以一次性表示复杂的旋转和平移")
print("2. 旋转顺序对最终结果有重要影响")
print("3. 分步变换的等效矩阵可以通过矩阵乘法得到")
print("4. 使用变换矩阵比手动分步更高效且不易出错")