Math 两个欧拉角或四元数之间的角度,万向节锁
我有惯性测量单元传感器,可以输出四元数或欧拉角的数据。作为一个生物机制学家,欧拉角对我来说更有意义,但我也了解四元数,但我从未真正研究过它们。我有数学背景,所以我并没有完全迷茫,我理解欧拉角中的万向锁效应 我想计算两个向量之间的角度,不管它们是四元数还是欧拉角,特别是在人体上我基本上想找到旋转轴并计算三个基本组件(Math 两个欧拉角或四元数之间的角度,万向节锁,math,rotation,quaternions,Math,Rotation,Quaternions,我有惯性测量单元传感器,可以输出四元数或欧拉角的数据。作为一个生物机制学家,欧拉角对我来说更有意义,但我也了解四元数,但我从未真正研究过它们。我有数学背景,所以我并没有完全迷茫,我理解欧拉角中的万向锁效应 我想计算两个向量之间的角度,不管它们是四元数还是欧拉角,特别是在人体上我基本上想找到旋转轴并计算三个基本组件(x,y,z)的角度差,而且一个人似乎不太可能扭曲身体并达到万向节锁 我已经读过了,似乎你选择的旋转方式(x->y->z将你带到与x->z->y->y相同的点,但在角度上是不同的路径)是
x
,y
,z
)的角度差,而且一个人似乎不太可能扭曲身体并达到万向节锁
我已经读过了,似乎你选择的旋转方式(x->y->z
将你带到与x->z->y->y相同的点,但在角度上是不同的路径)是万向节锁发挥作用的地方,但是提议的XZ'y''序列似乎完全避免了万向节锁
我已经读到四元数对于计算机来说更容易计算,这是我想继续使用四元数的地方,因为我使用的是圆周率,但我只是不完全理解如何从四元数到基本的x,y,z分量。所以我想我的问题是:
人体运动需要四元数吗
在最后一步计算角度并转换为Euler角度之前,将数字保持为四元数可以避免万向节锁吗
基本上,您有两个主要的工作选项,例如使用骨架
- 使用4x4矩阵(允许旋转和平移)
- 旋转使用(单位)四元数,平移使用偏移
如果你看一个函数的典型实现,它取2个向量并返回一个四元数,给出它们之间的旋转,你会发现它不仅仅是一个简单的公式。正在确定和处理边缘案件
let rotFromVectors(v1:vec3)(v2:vec3):quat=
设PI=System.Math.PI
设π乘以π=π/2.0
设2_PI=2.0*PI
设零旋转=quat(0.0f,0.0f,0.0f,1.0f)
设aabb=sqrt(float(vec3.dot(v1,v1))*float(vec3.dot(v2,v2)))
如果aabb 0.0
然后
设ab=float(vec3.dot(v1,v2))/aabb
设c=
vec3
(float32((float v1.y*float v2.z-float v1.z*float v2.y)/aabb)
,float32((float v1.z*float v2.x-float v1.x*float v2.z)/aabb)
,float32((float v1.x*float v2.y-float v1.y*float v2.x)/aabb)
)
设cc=float(vec3.dot(c,c))
如果cc 0.0
然后
让我们=
将ab>-sin(π乘以二)与//0.707107f匹配
|正确->1.0+ab
|假->抄送/(1.0+sqrt(1.0-抄送))
设m=sqrt(cc+s*s)
quat(浮点数32(浮点数c.x/m)、浮点数32(浮点数c.y/m)、浮点数32(浮点数c.z/m)、浮点数32(s/m))
其他的
如果ab>0.0
然后
零旋转
其他的
设m=sqrt(v1.x*v1.x+v1.y*v1.y)
如果(m 0.0f)
然后
夸脱(v1.y/m、(-v1.x)/m、0.0f、0.0f)
其他的
夸脱(1.0华氏度,0.0华氏度,0.0华氏度,0.0华氏度)
其他的
零旋转
其中,quat
是四元数的类型,vec3
是上述代码中3D向量的类型
通过四元数旋转向量的代码与数学建议的一样简单:
让旋转因子(alpha:quat)(v:vec3):vec3=
设s=vec3.v
四元逆α*(向量四元五)*α|>pureQuatToVec |>fun v'->v'*s
最后,并非最不重要的是(一些…欧拉角-实际上有24种不同版本的欧拉角,12种固定角旋转,12种连续旋转)之间的转换函数使用半角方法
让eulerToRot(v:vec3):quat=
设d=0.5F
设t0=cos(v.z*d)
设t1=sin(v.z*d)
设t2=cos(v.y*d)
设t3=sin(v.y*d)
设t4=cos(v.x*d)
设t5=sin(v.x*d)
夸脱
(t0*t3*t4-t1*t2*t5)
,t0*t2*t5+t1*t3*t4
,t1*t2*t4-t0*t3*t5
,t0*t2*t4+t1*t3*t5
)
|>四规范化
让轮虫(q:quat):vec3=
设ysqr=q.y*q.y
//滚动(x轴旋转)
设t0=+2.0f*(q.w*q.x+q.y*q.z)
设t1=+1.0f-2.0f*(q.x*q.x+ysqr)
让滚动=atan2 t0 t1
//节距(y轴旋转)
设t2=
设t2'=+2.0f*(q.w*q.y-q.z*q.x)
将t2'与
|_uu当t2'>1.0f->1.0f时
|当t2'<-1.0f->-1.0f时
|->t2'
让螺距=asin t2
//偏航(z轴旋转)
设t3=+2.0f*(q.w*q.z+q.x*q.y)
设t4=+1.0f-2.0f*(ysqr+q.z*q.z)
让偏航=atan2 t3 t4
vec3(横滚、俯仰、偏航)
要知道的最后一个技巧是,将向量转换为(纯)四元数对于rotativector
函数非常方便
让vecToPureQuat(v:vec3):quat=
夸脱(v.x、v.y、v.z、0.0f)
让pureQuatToVec(q:quat):vec3=
vec3(q.x,q.y,q.z)
那么,回答你的主要问题:四元数是必要的吗?不,你也可以使用4x4矩阵
如果它认为你有用,你可以从一个转到另一个:
let offsetAndRotToMat(offset:vec3)(q:quat):mat4=
让ux=v3 1 0 0
设uy=v3 0 1 0
设uz=v3 0 1
设rx=旋转因子q ux
设ry=旋转因子q uy
设rz=旋转因子q uz
mat4
(
rx.x,rx.y,rx.z,0.0f,
ry.x,ry。