一文弄懂四元数的使用以及与欧拉角的关系(附带MATLAB演示)

四元数的使用

四元数可以理解成一个四维空间的量(其由四个变量组成),常用在三维旋转坐标下求取一个向量的坐标。四元数可以抽象地理解成对一种三维旋转方式的代表,这个旋转方式由两部分组成:一部分是旋转轴,这个可以用一个三维向量表示 v = ( v x , v y , v z ) v = (v_x,v_y,v_z) v=(vx,vy,vz),另一部分则是坐标系顺该旋转轴旋转角度,逆时针为正,例如 θ \theta θ

再已知这两部分的前提下,旋转操作是唯一的,我们用四元数来表示这种旋转操作,记为:
q = ( c o s θ 2 , v x s i n θ 2 , v y s i n θ 2 , v z s i n θ 2 ) q = (cos\frac{\theta}{2},v_xsin\frac{\theta}{2},v_ysin\frac{\theta}{2},v_zsin\frac{\theta}{2}) q=(cos2θ,vxsin2θ,vysin2θ,vzsin2θ)
现在假如我们已知一个三维向量 h = ( x , y , z ) h=(x,y,z) h=(x,y,z),我们想知道在 q q q这种旋转操作下在新坐标系 h ′ h' h的坐标,该怎么办?

下面解决方法我们不谈为什么,只讲怎么解决。

引入纯四元数这个概念,什么叫纯四元数,就是四元数有一个分量为0,然后将 h h h扩充为纯四元数 h 4 = ( 0 , x , y , z ) h_4=(0,x,y,z) h4=(0,x,y,z)也就是三维量变四维量,但事实上这个纯四元数也只是四维空间的一个三维超平面而已。

那么经过 q q q旋转后在新坐标系下 h ′ h' h的坐标可以用如下四元数表示:
h ′ = q − 1 v q h'=q^{-1}vq h=q1vq
上面这个式子用到了四元数的乘法,下面引出四元数乘法的公式:( q 1 = ( w 1 , x 1 , y 1 , z 1 ) , q 2 = ( w 2 , x 2 , y 2 , z 2 ) q_1=(w_1,x_1,y_1,z_1),q_2=(w_2,x_2,y_2,z_2) q1=(w1,x1,y1,z1),q2=(w2,x2,y2,z2))
q 1 ∗ q 2 = ( w 1 w 2 − x 1 x 2 − y 1 y 2 − z 1 z 2 , w 1 x 2 + x 1 w 2 + y 1 z 2 − z 1 y 2 , w 1 y 2 − x 1 z 2 + y 1 w 2 + z 1 x 2 , w 1 z 2 + x 1 y 2 − y 1 x 2 + z 1 w 2 ) q_1*q_2=(w_1w_2-x_ 1x_2-y_1y_2-z_1z_2,w_1x_2+x_1w_2+\\y_1z_2-z_1y_2,w_1y_2-x_1z_2+y_1w_2+z_1x_2,w_1z_2+x_1y_2\\-y_1x_2+z_1w_2) q1q2=(w1w2x1x2y1y2z1z2,w1x2+x1w2+y1z2z1y2,w1y2x1z2+y1w2+z1x2,w1z2+x1y2y1x2+z1w2)

同样,一个四元数的共轭(逆运算)定义为:
q − 1 = ( w , − x , − y , − z ) q^{-1}=(w,-x,-y,-z) q1=(w,x,y,z)
最后旋转后向量的坐标 h ′ h' h的后三个分量
下面先给出乘法和逆运算的MATLAB函数:

function result = quaternionMultiplication(q1,q2)
result(1) = q1(1)*q2(1) - q1(2)*q2(2) - q1(3)*q2(3) - q1(4)*q2(4);
result(2) = q1(1)*q2(2) + q1(2)*q2(1) + q1(3)*q2(4) - q1(4)*q2(3);
result(3) = q1(1)*q2(3) - q1(2)*q2(4) + q1(3)*q2(1) + q1(4)*q2(2);
result(4) = q1(1)*q2(4) + q1(2)*q2(3) - q1(3)*q2(2) + q1(4)*q2(1);
end
function result = quaternionInv(q1)
result(1) = q1(1);
result(2) = -q1(2);
result(3) = -q1(3);
result(4) = -q1(4);
end

四元数 q − 1 v q q^{-1}vq q1vq q v q − 1 qvq^{-1} qvq1区别

区别在于旋转方向发生改变:

psai = pi/4; phi = pi/6; theta = pi/3;

q1 = [cos(psai/2),0,0,sin(psai/2)];

v1 = [0,1,1,0]; sqrt(sum(v1.^2))
% temp1 = quaternionMultiplication(q1,v1);
% temp2 = quaternionInv(q1);
% vRotation1 = quaternionMultiplication(temp1,temp2);
% vRotation1 = vRotation1(2:4)
% sqrt(sum(vRotation1.^2))
temp1 = quaternionMultiplication(quaternionInv(q1),v1);
vRotation1 = quaternionMultiplication(temp1,q1);
vRotation1 = vRotation1(2:4)
sqrt(sum(vRotation1.^2))

figure();
v2 = [1,1,0];
plot3([0,vRotation1(1)],[0,vRotation1(2)],[0,vRotation1(3)],"r","LineWidth",3);
hold on;
plot3([0,v2(1)],[0,v2(2)],[0,v2(3)],"b","LineWidth",3);
grid on;

注释和非注释部分演示了两种计算方式,并绘图。
这是 q − 1 v q q^{-1}vq q1vq:
在这里插入图片描述
蓝色为旋转前矢量,红色为旋转后矢量,可以看到这个旋转操作是以z轴为旋转轴逆时针旋转45°。

这是 q v q − 1 qvq^{-1} qvq1:
在这里插入图片描述
对比得知,旋转方向相反!

欧拉角的劣势

欧拉角通过 θ ϕ ψ \theta \phi \psi θϕψ确定一个旋转后坐标系,当然,有一个明显缺点就是必须给定旋转顺序,先转 θ \theta θ再转 ψ \psi ψ和先转 ψ \psi ψ再转 θ \theta θ是不一样的,一般规定顺序为 ψ θ ϕ \psi \theta \phi ψθϕ。对应角度如下:
在这里插入图片描述
而四元数是可以区分先后顺序的,例如:
v ′ = q 3 − 1 q 2 − 1 q 1 − 1 v q 1 q 2 q 3 v'=q_3^{-1}q_2^{-1}q_1^{-1}vq_1q_2q_3 v=q31q21q11vq1q2q3
顺序是先 q 1 q_1 q1 q 2 q_2 q2 q 3 q_3 q3

MATLAB验证欧拉角和四元数一一对应性

我们定义三个旋转操作, q 1 q_1 q1为绕z轴45°, q 2 q_2 q2为绕x轴30°, q 3 q_3 q3为绕y轴60°。验证利用四元数计算结果和欧拉角旋转矩阵计算结果的一致性。
考虑到欧拉角旋转矩阵与旋转顺序有关,定义顺序为 ψ θ ϕ \psi \theta \phi ψθϕ
待旋转的向量:
v = ( 1 , 2 , 3 ) v=(1,2,3) v=(1,2,3)

%-------------------四元数----------------------------%
psai = pi/4; phi = pi/6; theta = pi/3;

q1 = [cos(psai/2),0,0,sin(psai/2)];
q2 = [cos(theta/2),0,sin(theta/2),0];
q3 = [cos(phi/2),sin(phi/2),0,0];

v1 = [0,1,2,3]; sqrt(sum(v1.^2))

temp1 = quaternionMultiplication(q1,q2);
temp2 = quaternionMultiplication(temp1,q3);
temp3 = quaternionInv(temp2);
temp4 = quaternionMultiplication(temp3,v1);
vRotation1 = quaternionMultiplication(temp4,temp2);
vRotation1 = vRotation1(2:4)
sqrt(sum(vRotation1.^2))

v2 = [1,2,3];
Cbn = [cos(psai)*cos(theta),cos(psai)*sin(theta)*sin(phi)-sin(psai)*cos(phi),...
    sin(theta)*cos(phi)*cos(psai)+sin(phi)*sin(psai);...
    sin(psai)*cos(theta),cos(phi)*cos(psai)+sin(phi)*sin(theta)*sin(psai),...
    sin(theta)*cos(phi)*sin(psai)-sin(phi)*cos(psai);...
    -sin(theta),cos(theta)*sin(phi),cos(theta)*cos(phi)
    ]';

vRotation2 = Cbn * v2'
sqrt(sum(vRotation2.^2))

figure();
plot3([0,vRotation1(1)],[0,vRotation1(2)],[0,vRotation1(3)],"r","LineWidth",3);
hold on;
plot3([0,vRotation2(1)],[0,vRotation2(2)],[0,vRotation2(3)],"g","LineWidth",3);
plot3([0,v2(1)],[0,v2(2)],[0,v2(3)],"b","LineWidth",3);
grid on;

在这里插入图片描述
在这里插入图片描述
红色和绿色向量重合,蓝色为原始向量,可以看出结果一致。

值得一提的是,这两种运算都有保范性,模不变。

猜你喜欢

转载自blog.csdn.net/weixin_43145941/article/details/109629526
今日推荐