这些向量都是3维向量(x,y,z)。
我有一个暴力算法,但我几乎确定有一种更简单的解决方法。我的网络搜索还没有揭示出一个。
我正在使用C#,但如果您有C、FORTRAN、Basic等内容,我可以转换它。或者,我可以使用数学上书写的术语。
该应用程序用于确定航天器所需的方向,以便刚性附着在其上的光学设备能够正确对准拍摄。 (必须同时对齐两个向量,即瞄准方向和关于瞄准方向旋转光学装置的适当旋转。)该计算可能在由实时感测数据提供的循环中使用,并且暴力解决方案速度太慢。
由于它们都是正交单位向量,你只需要再添加一个来构造一个基(使用叉积)。现在你有两个基础{A,B,AXB}和{C,D,CxD}。将{A,B}移动到{C,D}的旋转将重新表达一个向量a1A + a2B + a3(AXB)作为b1C + b2D + b3(CxD)。因为它是线性的,你只需要知道它在基础上的行为(这确定了线性变换)。因此,以{A,B,...}为我们的基础,并让变换为T,我们看到T(1,0,0)= C,T(0,1,0)= D和T(0,0,1)= CxD。记住A =(1,0,0)等等。但这个矩阵的列只是M =(C,D,CxD)。
https://alleg.svn.sourceforge.net/svnroot/alleg/allegro_outdated/branches/allegro/src/math3d.c
几乎完成了3D图形的代码...请查看底部以...开头的函数。
get_align_matrix_f
同样的,四元数也是一样的...
https://alleg.svn.sourceforge.net/svnroot/alleg/allegro_outdated/branches/allegro/src/quat.c
同样在矩阵中,它可能无法为您提供从向量A到C的最短(或直接)路径,因此如果您正在制作动画可视化效果,则最好使用四元数。
考虑到航天器的成本高达数亿美元,您可能希望找到一个能够轻松完成此类任务并要求他们生成一个经过验证和优化的解决方案,包括代码,而不是仅依靠这里的描述。(除非这只是一种练习。)
此外,您选择的解决方案应该非常依赖于航天器上可用的推进器;您希望旋转使用尽可能少的燃料,这将取决于它们对航天器的内在影响。我假设您已经设置了问题,使得一个旋转轴围绕z轴旋转;您是否还可以独立地围绕x和y旋转,或者只有另一个轴?某些旋转是否比其他旋转更昂贵(例如由于沿某些轴的不同惯性矩)?
考虑到这些限制,我非常犹豫给出如下建议:找到将A移动到C所需的旋转轴(A x C),并进行旋转(参见维基百科关于绕轴旋转的内容)。然后通过将旋转矩阵乘以B来计算B的变化,并计算B和D之间的夹角;最后,沿着(B x D)轴旋转--此时该轴必须与C轴相同--以修正差异(得到另一个旋转矩阵)。将两个矩阵相乘,完成。
虽然我知道这篇文章发表已经有一段时间了,但是如果你也遇到了列/行主要性和左/右手混淆的问题,并且想将Mark T的优秀结果编码成WPF,你可以像这样做:
static public Matrix3D TwistToNewAxes(Vector3D A, Vector3D B, Vector3D D, Vector3D E)
{
Vector3D C = Vector3D.CrossProduct(B, A);
Vector3D F = Vector3D.CrossProduct(E, D);
Matrix3D result = Matrix3D.Identity;
result.M11 = D.X * A.X + E.X * B.X + F.X * C.X;
result.M21 = D.X * A.Y + E.X * B.Y + F.X * C.Y;
result.M31 = D.X * A.Z + E.X * B.Z + F.X * C.Z;
result.M12 = D.Y * A.X + E.Y * B.X + F.Y * C.X;
result.M22 = D.Y * A.Y + E.Y * B.Y + F.Y * C.Y;
result.M32 = D.Y * A.Z + E.Y * B.Z + F.Y * C.Z;
result.M13 = D.Z * A.X + E.Z * B.X + F.Z * C.X;
result.M23 = D.Z * A.Y + E.Z * B.Y + F.Z * C.Y;
result.M33 = D.Z * A.Z + E.Z * B.Z + F.Z * C.Z;
return result;
}
非常感谢 Mark!