matlab四元数函数,四元数插值matlab实现

看了几个关于关键帧提取和关键帧插值的论文,有几篇讲到了四元数插值这个概念

关于欧拉角到四元数的转换,请看:刚体运动研究方法——欧拉角四元数

接下来介绍四元数的插值公式以及matlab实现

插值公式可以从论文论文理解——从运动捕获数据中提取关键帧中找到,在这里再写一遍

a693bfb985ba07198730162dacf7c08d.png

61df888f4f75ff824496d1865daf0119.png

这里的 t 代表的是在夹角的哪一部分插值,从下图可以看出来,图中的ang=θ

6af9cb06b03b60b4ad6fb8c059a4d3b8.png

话不多说,上代码(matlab实现):

网上摘取的,地方忘记了,并且经过了一个小小的修改

SlepInsert.m

function r= SlerpInsert(p,q,t)

%球面线性插值

%程序考虑了p、q点乘结果为负的情况

%返回的插值结果是r

w0=p(1);x0=p(2);y0=p(3);z0=p(4);

w1=q(1);x1=q(2);y1=q(3);z1=q(4);

%用点乘计算两个四元数夹角的cos值

cosOmega=w0*w1+x0*x1+y0*y1+z0*z1;

%如果点乘为负,则反转一个四元数以取得短的4D弧

if(cosOmega<0.0)

w1=-w1;

x1=-x1;

y1=-y1;

z1=-z1;

cosOmega=-cosOmega;

end

%检查他们是否接近,以避免除零

m=size(t,2);%火啊去插值精度,即需要分别在哪一部分插值

for i=1:m

if cosOmega>0.99999999 %cos=1的时候就是夹角为0,重合

k0=1.0-t(i);

k1=t(i);

else

%用三角公式sin?+cos?=1计算sin值

sinOmega=sqrt(1.0-cosOmega*cosOmega);

%通过sin和cos计算角度

omega=atan2(sinOmega,cosOmega) %计算点(cosOmega,sinOmega)与x轴正向的夹角

%计算分母的倒数,这样就只需要一次除法

oneOverSinOmega=1.0/sinOmega;

%计算插值变量

k0=sin((1.0-t(i))*omega)*oneOverSinOmega;

k1=sin(t(i)*omega)*oneOverSinOmega;

end

%插值

w=w0*k0+w1*k1;

x=x0*k0+x1*k1;

y=y0*k0+y1*k1;

z=z0*k0+z1*k1;

r(i,1)=w; r(i,2)=x; r(i,3)=y; r(i,4)=z;

end

SerpInsertTest.m

clear

clc

q=[1 2 3 4];

p=[1 3 6 8];

t=0:0.5:2*pi;

r=SlerpInsert(p,q,t);结果:

r =

1.0000 3.0000 6.0000 8.0000

1.0000 2.5000 4.5000 6.0000

1.0000 2.0000 3.0000 4.0000

1.0000 1.5000 1.5000 2.0000

1.0000 1.0000 0 0

1.0000 0.5000 -1.5000 -2.0000

1.0000 0 -3.0000 -4.0000

1.0000 -0.5000 -4.5000 -6.0000

1.0000 -1.0000 -6.0000 -8.0000

1.0000 -1.5000 -7.5000 -10.0000

1.0000 -2.0000 -9.0000 -12.0000

1.0000 -2.5000 -10.5000 -14.0000

1.0000 -3.0000 -12.0000 -16.0000

按照论文思想就是酱紫啦,如果需要在OpenGL里面实现的话,请参考网络里面的大牛们的文章。