我有两个矢量对(旋转前后)。
旋转前: [X1,Y1,Z1] [X2,Y2,Z2]
旋转后: [X1' ,Y1' ,Z1' ] [X2' ,Y2' ,Z2' ]
如何创建表示此旋转的四元数?
答案 0 :(得分:2)
那么,首先你可以使用向量乘法(交叉乘法)找到旋转轴:
axis = v1 x v2;
然后你可以计算旋转角度:
sinA = |axis| / |v1|*|v2|
cosA = v1 . v2 / |v1|*|v2|
这里| | - 是矢量长度操作,和。 - 是点乘法
最后,你的四元数是:
Q(w,x,y,z) = (cosA, axis.x * sinA, axis.y * sinA, axis.z * sinA)
答案 1 :(得分:1)
在大多数情况下,没有旋转将2个向量转换为2个其他向量。这是一种可视化原因的简单方法:旋转不会改变矢量之间的角度。如果旋转前2个矢量之间的角度与旋转后2个矢量之间的角度不同,则没有符合您标准的旋转。
这就是说可能存在一个具有可接受误差的最佳四元数,它几乎“旋转”你的2个矢量对。有许多算法在速度和精度上有所不同以找到这样的四元数。我为Arduino应用程序编写了一个快速C ++算法,其中速度很关键,但精度不太重要。
旋转前:u0,v0。轮换后:u2,v2。
Quaternion q2 = Quaternion::fromTwoVectors(u0, u2);
Vector v1 = v2.rotate(q2.conjugate());
Vector v0_proj = v0.projectPlane(u0);
Vector v1_proj = v1.projectPlane(u0);
Quaternion q1 = Quaternion::fromTwoVectors(v0_proj, v1_proj);
return (q2 * q1).normalized();
如果这不符合您自己的应用程序的要求,请尝试google Wabha的问题。
答案 2 :(得分:1)
我将marcv81非常有用的博客文章翻译成Three.js:
const rotateVectorsSimultaneously = (u0, v0, u2, v2) => {
const q2 = new THREE.Quaternion().setFromUnitVectors(u0, u2);
const v1 = v2.clone().applyQuaternion(q2.clone().conjugate());
const v0_proj = v0.projectOnPlane(u0);
const v1_proj = v1.projectOnPlane(u0);
let angleInPlane = v0_proj.angleTo(v1_proj);
if (v1_proj.dot(new THREE.Vector3().crossVectors(u0, v0)) < 0) {
angleInPlane *= -1;
}
const q1 = new THREE.Quaternion().setFromAxisAngle(u0, angleInPlane);
const q = new THREE.Quaternion().multiplyQuaternions(q2, q1);
return q;
};
由于angleTo
始终返回正值,因此我根据u0
-v0
平面v1
的哪一侧在边上手动翻转角度的符号。 / p>
答案 3 :(得分:0)
针对此问题的成熟解决方案称为 Triad 。 Triad是解决航天器姿态确定问题的最早,最简单的方法之一,并且计算效率很高。
使用Triad的想法是用成对的三个向量替换成对的两个向量集,其中多余的向量与叉积生成。通过对向量进行归一化,您可以求解没有矩阵逆或SVD的旋转矩阵(在问题的更一般情况下需要-请参见 Wahba问题)
有关完整算法,请参见:https://en.wikipedia.org/wiki/Triad_method
然后您可以将求解的旋转矩阵从Triad转换为旋转四元数:
qw = √(1 + m00 + m11 + m22) /2
qx = (m21 - m12)/( 4 *qw)
qy = (m02 - m20)/( 4 *qw)
qz = (m10 - m01)/( 4 *qw)
通常,为了使四元数转换更可靠,您应该考虑查看矩阵轨迹,如下所述:http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
最后,考虑使用Triad的替代方法,直接计算最优四元数称为 QUEST 。
答案 4 :(得分:0)
可以找到从v1到v2的四元数。
最后一个q = (cos A/2, sin A/2 * axis)
,其中A是v1和v2之间的夹角,axis是标准轴。
将两边都乘以2 * cos A/2
,
那么我们有
2 * cos A/2 *q = (1+cos A, sin A * axis)
(其中cos A = dot(v1, v2)/|v1|/|v2|
和
axis = cross(v1, v2).normalize() = cross(v1, v2)/|v1|/|v2|/sin A
。)
然后2 * cos A/2 *q = (1+dot(v1, v2)/|v1|/|v2|, cross(v1, v2)/|v1|/|v2|)
最后q = (1+dot(v1, v2)/|v1|/|v2|, cross(v1, v2)/|v1|/|v2|).normalize()