You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SciPy Rotation仅调用inv()时输出正确结果,问题排查求助

旋转矩阵实现SciPy调用异常问题排查

问题描述

我有一个通过旋转矩阵和NumPy对欧拉角输入执行旋转的函数,该函数已在多架无人机的实时飞行控制环路中运行,正确性得到验证。
我尝试使用SciPy Rotation实现相同功能,直接编写代码得到的输出完全异常,但无理由添加inv()调用后却能输出正确结果,请问问题出在哪里?
VF、BUL和VTOL为不同的参考坐标系,我从yaml文件加载旋转矩阵。我的输入vehicle_rph是VF坐标系下测得的向量时序数组,需要得到其在VTOL坐标系下的对应值。yaml中所有矩阵均以BUL为参考基准,因此要实现VF到VTOL的转换,需要走VF→BUL→VTOL的路径。
以下我分别用NumPy和SciPy各实现了一次转换流程,可以看到经验证正确的NumPy输出,仅与我额外添加了inv()的SciPy输出匹配。如果能告知Z轴结果存在微小差异的原因会额外感谢,目前该偏差已满足我的使用需求。

输入代码

# 使用NumPy数组实现
R_VF_from_BUL = frames['frames']['VF']['R_vf_from_bul']
R_VTOL_from_BUL = frames['frames']['VTOL-B']['R_vtolb_from_bul']
R_BUL_from_VF = np.transpose(R_VF_from_BUL)
R_VTOL_from_VF = np.matmul(R_VTOL_from_BUL, R_BUL_from_VF)

# 使用SciPy Rotation实现
r_vf_from_bul = R.from_matrix(frames['frames']['VF']['R_vf_from_bul'])
r_vtol_from_bul = R.from_matrix(frames['frames']['VTOL-B']['R_vtolb_from_bul'])
r_bul_from_vf = r_vf_from_bul.inv()
r_vtol_from_vf = r_vtol_from_bul*r_bul_from_vf

print(f'NumPy计算结果:\n{R_VTOL_from_VF}')
print('')
print(f'SciPy计算结果:\n{r_vtol_from_vf.as_matrix()}')

vehicle_rph_vtol_sp = (r_vtol_from_vf*R.from_euler('XYZ', vehicle_rph)).as_euler('XYZ')
vehicle_rph_vtol_sp_inv = (r_vtol_from_vf.inv()*R.from_euler('XYZ', vehicle_rph)).as_euler('XYZ')
vehicle_rph_vtol_np = transform_euler_angles_signal_to_vtol_from_vf_frame(vehicle_rph)

print('')
print(f'常规SciPy输出: {vehicle_rph_vtol_sp[0]}')
print(f'加inv()的SciPy输出: {vehicle_rph_vtol_sp_inv[0]}')
print(f'NumPy基准输出: {vehicle_rph_vtol_np[0]}')

输出结果

NumPy计算的旋转矩阵:
[[ 0.52205926  0.          0.85290921]
 [ 0.          1.          0.        ]
 [-0.85290921  0.          0.52205926]]

SciPy计算的旋转矩阵:
[[ 0.52205926  0.          0.85290921]
 [-0.          1.          0.        ]
 [-0.85290921 -0.          0.52205926]]

常规SciPy输出: [-3.11319763  1.13894171 -1.90741245]
加inv()的SciPy输出: [-0.01189337 -0.04056495  1.25948718]
NumPy基准输出: [-0.01189337 -0.04056495  1.29595719]

问题解答

1. 为什么加inv()后输出才正确

你混淆了向量坐标系转换和姿态参考系转换的旋转方向:
你通过NumPy计算得到的R_VTOL_from_VF矩阵,作用是将VF坐标系下的向量坐标转换为VTOL坐标系下的坐标,运算逻辑为v_VTOL = R_VTOL_from_VF @ v_VF。
但你后续处理的vehicle_rph是欧拉角表示的姿态,本质是机体相对于VF参考系的旋转变换。当你需要把这个姿态的参考系从VF切换到VTOL时,所需的旋转变换就是R_VTOL_from_VF的逆(旋转矩阵是正交矩阵,逆等于转置),这就是你额外加inv()后结果能和NumPy输出匹配的根本原因。
补充:你构造r_vtol_from_vf的逻辑完全正确,输出的旋转矩阵和NumPy计算结果一致,问题出在对姿态做坐标系转换时的旋转方向搞反了。

2. Z轴结果存在微小差异的原因

这个差异来自欧拉角旋转约定的不一致:
SciPy的R.from_euler('XYZ', value)中大写的XYZ对应的是**内旋(intrinsic)顺序,即每次旋转都绕上一次旋转后的机体轴转动;而你自己实现的NumPy版本函数用的是外旋(extrinsic)**顺序,每次旋转都绕固定的参考系轴转动。两者的旋转顺序约定不同,最终解算出来的欧拉角就会出现小范围的偏差。你可以把SciPy调用里的'XYZ'改为小写'xyz',就可以对齐两个实现的欧拉角约定,消除Z轴的数值差异。

内容的提问来源于stack exchange,提问作者PHinchey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 19:09:02