Rotate a Vector3 by a Rotation Vector3 用“旋转向量”旋转向量

rotate v:
被旋转的向量v:


by "rotation vector" r:
“旋转轴向量”r:


where angle θ=||r||
旋转角度θ即r的长度



旋转矩阵或者四元数都是“状态/瞬态转换”,你不知道正转反转、转了/要转多少圈,角速度是多少。四元数反求旋转轴与角度(《slerp》),接近0、旋转整周的时候也是有奇点的。qvq*的两面包夹芝士方法,虽然省点算力和空间,但不太易懂。

旋转轴+旋转角(Axis-Angle)的方法,维基有很多个,即使提到了R=exp(θK)《e的矩阵次方》,但K的内容总是要把旋转向量归一化成单位向量再转为“叉乘矩阵”,θ又是向量长度,又乘回去了。

而实际上直接用旋转向量在接近0的时候可以愉快地级数展开,不用单位化,即不需要除法更不用平方根,也就是只用θ²即可干活。

R=exp(θK)=I+sinθ·K+(1-cosθ)K² ←常见的公式是这么整的,然而你还可以:

R=exp([旋转向量r]×)=exp(《r不用单位化直接转为“叉乘矩阵”干脆就叫C罢》)=exp(C)=I+(sinθ/θ)C+((1-cosθ)/θ²)C²

↑=I+C/1!+C²/2!-tC/3!-tC²/4!+t²C/5!+t²C²/6!-t³C/7!-t³C²/8!+……
(t=r·r=||r||²=θ²=x²+y²+z², C=[0,-z,y
z,0,-x
-y,x,0
], C²=[-y²-z²,xy,xz
xy,-x²-z²,yz
xz,yz,-x²-y²
], C³=-tC)

然鹅如果角度(r长度)大了还是平方根再丢给sincos去对2π取模好点不然收敛太慢精度没了(建议手动从头限制旋转角范围,实践上要做到这一步多次计算还是缓存一个单位旋转轴(Versor)和旋转角度(除以π的,用时取小数后再乘π)比较好(至少不用对不明向量归一化(对我就是看他不爽(((

好吧其实就是K=C/θ提取出来了(但在sin cos展开式中把除的θ算进去每项次数降低,就不用再除,干脆直接自己算展开式

数学爷爷们倒是早就搞清楚了,四元数分析,李代数,可除代数,Banach代数,但是本数学渣程序猿去钻通可能要掉几层皮(参见罗德里格斯(Rodrigues's rotation formula)公式(

(跟exp(纯虚四元数“矢量四元数”v)还是不太一样的,exp(xi+yj+zk)即exp(v)=cosθ+v*sinθ/θ=cosθ+“v的单位化”*sinθ其中θ=√(x²+y²+z²),它表示单位向量在实轴和v(单位化)张成的二维平面上(在四维空间中)转圈圈,有实部也就是一般化的exp(q)依然是在此基础上放大缩小exp(实部)倍,总之跟常见教程里那个qvq*的q不是一个东西)

虽然降维回去光看复数exp(xi)在复平面转圈圈貌似效果一样(但复数时两者都是二维,升级后一个是三维旋转一个是四维旋转,仔细品味(真正一般化的四维旋转又是另一回事了,旋转本质是“在一个二维平面中保持相同距离运动”,对偶的那个“旋转轴”就不是一条直线,而是“另一个二维平面”了。

闲还可以去玩更野的七维旋转七维叉乘与八元数(

cosq?

屁牌实(mei)用数学系列。更新日期:2023-11-12。随时可能更新。以WTFPL协议发布。