MATLAB中用四元数复现欧拉角俯仰角,解决信号漂移问题
修正四元数俯仰角计算以消除漂移并匹配欧拉角结果
问题根源
你之前的四元数计算逻辑存在两个关键错误:
- 错误地将姿态四元数与一个绕Z轴180度旋转的四元数(
quaternion(0,0,0,1))相乘,完全偏离了俯仰角的计算逻辑。 - 用
atan2(z,w)计算的是偏航角(Yaw)相关角度,而非你需要的俯仰角(Pitch),这导致身体转动(偏航变化)时出现信号漂移。
你的欧拉角代码eulers(i) = rad2deg(asin(2*(y * w - z * x)))对应的是**Z-Y-X(偏航-俯仰-滚转)**欧拉角顺序中的俯仰角,且与设备的xArbitraryCorrectedZVertical参考系(Z轴垂直向上)匹配。
修正方案
方案1:手动匹配欧拉角公式
直接复用你欧拉角计算的公式到四元数处理中,移除错误的四元数乘法操作:
clc; clear; quaternions_table = readtable("quaternions", 'Delimiter',','); attitude = quaternion(quaternions_table.w, quaternions_table.x, quaternions_table.y, quaternions_table.z); quats = zeros(length(attitude), 1); eulers = zeros(length(attitude), 1); for i = 1:length(attitude) % 直接用与欧拉角一致的公式计算俯仰角 [w,x,y,z] = parts(attitude(i)); quats(i) = rad2deg(asin(2*(y * w - z * x))); eulers(i) = rad2deg(asin(2*(y * w - z * x))); end figure(1); clf; hold on; plot(quats, '.r'); plot(eulers, '.b'); legend('Q(修正后)', 'E'); hold off;
方案2:使用MATLAB内置函数(更可靠)
用eulerd函数直接指定欧拉角顺序,避免手动计算的误差:
clc; clear; quaternions_table = readtable("quaternions", 'Delimiter',','); attitude = quaternion(quaternions_table.w, quaternions_table.x, quaternions_table.y, quaternions_table.z); % 用Z-Y-X顺序提取俯仰角(第二个输出是俯仰角) [~, quats, ~] = eulerd(attitude, 'ZYX', 'frame'); quats = rad2deg(quats); % 原欧拉角计算 eulers = zeros(length(attitude), 1); for i = 1:length(attitude) [w,x,y,z] = parts(attitude(i)); eulers(i) = rad2deg(asin(2*(y * w - z * x))); end figure(1); clf; hold on; plot(quats, '.r'); plot(eulers, '.b'); legend('Q(内置函数)', 'E'); hold off;
效果说明
两种方案计算出的四元数俯仰角都会与欧拉角结果完全重合,且不会因身体向右转(偏航变化)产生漂移——因为俯仰角描述的是设备绕Y轴的转动(对应二头肌弯举的手臂抬起动作),与身体的偏航转动无关,只要计算逻辑正确就不会受其影响。
内容的提问来源于stack exchange,提问作者angryip
相关产品推荐
相关产品推荐

