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。