如何在不影响第三轴的情况下沿两个轴旋转矩阵?

How to rotate a matrix along two axis without affecting the third axis at all?

提问人:KiraHoneybee 提问时间:1/7/2023 最后编辑:KiraHoneybee 更新时间:1/9/2023 访问量:137

问:

我有一个对象,它需要旋转两个轴(为简单起见,我们称它们为 X 轴和 Y 轴,但要理解它们可以是完全任意的)。

所以,像这样的东西:

Matrix aMat;
aMat.RotateAroundAxis(Vector(1,0,0),45.0f);
aMat.RotateAroundAxis(Vector(0,1,0),25.8f);

执行此操作时,我会围绕我旋转的两个轴的叉积进行不必要的旋转(例如,在上面的示例中,我将围绕 z 轴或 0,0,1 进行一些(少量)旋转)。这是一个非常小的旋转量,但它足以被看到,特别是如果我做了很多旋转,它似乎会积累误差。

有没有办法压制它?

(编辑:如果对我正在做的事情有更好的解决方案,我有一个平台。我希望平台根据重量的位置旋转,就好像它在一个点上平衡一样。我通过围绕垂直于平台向上方向的两个正交轴累积旋转来做到这一点,具体取决于“重量”相对于平台中心的位置)

数学 矩阵乘法 OpenGL-3

评论

0赞 user253751 1/7/2023
不要做很多轮换。从一个新的矩阵开始,每次都从头开始进行整个旋转。旋转矩阵将始终累积数值误差。
0赞 KiraHoneybee 1/7/2023
没有其他选择?我必须编写的函数接受一个起始方向矩阵,以及权重和枢轴的位置,并期望返回一个矩阵,原始方向矩阵可以乘以该矩阵以产生新的倾斜矩阵(我只是一个大团队中的一个人)。它被反复调用,以在视觉上缓慢倾斜平台以适应重量。只要我把它限制在一个轴上,它总是完美的。当我涉及第二个垂直轴时,它开始累积误差。
1赞 user253751 1/7/2023
顺便说一句,这可能不仅仅是一个错误。如果在 X 轴上旋转,在 Y 轴上旋转,在 X 轴上向后旋转,在 Y 轴上向后旋转,即使没有错误,也会累积 Z 轴旋转,因为这就是旋转的工作原理。(你可以自己用立方体形状的物体试试)
0赞 KiraHoneybee 1/7/2023
我相信问题(在您的第二次回复中)有点像云台锁的反面,这是云台解锁...有没有办法纠正这个问题并保持 Z 轴完全锁定,没有技巧或秘密?
1赞 user253751 1/7/2023
我认为对于您的用例,您不希望进行两次单独的轮换。对于小旋转,它可能是一个足够好的惰性近似,因为“误差”很小。但是,我认为您真正想做的是计算一个轴(可能是 cross(Z, normalize(weightPos - pivotPos))),并围绕该轴旋转。

答:

1赞 G. Putnam 1/9/2023 #1

如果我了解您的问题设置,您会遇到以下情况:

  • Weight On Platform
  • 自己的作品

您的问题的简短回答(从平坦开始)是:

  • 找到权重位置的向量
  • 找到垂直于此向量和 Z 轴的向量
    • 找到的向量和 Z 轴的叉积
  • 绕垂直矢量旋转
  • 如果你“大部分”忽略了物理特性,而只是根据位置应用了一些旋转,则尤其如此。
  • 每次只需从平坦开始,然后根据上述方法旋转即可。

注意:如果你真的有一个这样的物理平台,并且显示的弹珠向左或向右徘徊,那么除非有一些物理机制来阻止旋转,否则平台实际上会先于此。

一般原因来自维基百科:旋转 “三维旋转通常不是可交换的,因此即使在同一点附近,应用旋转的顺序也很重要。”

考虑 3D 中的独立旋转矩阵(摘自维基百科:旋转矩阵)

R_x(α) = 
1      0      0
0      cos(α) -sin(α)
0      sin(α)  cos(α)
R_y(β) = 
 cos(β)  0      sin(β)
 0       1      0
-sin(β)  0      cos(β)
R_z(γ) = 
 cos(γ) -sin(γ) 0
 sin(γ)  cos(γ) 0
 0       0      1  

但是,如果你把它们放在一起,你会得到一堆组合术语。

R = R_z(γ), R_y(β), R_x(α) =
cos(β)cos(γ)    sin(α)sin(β)cos(γ)-cos(α)sin(γ)   cos(α)sin(β)cos(γ)+sin(α)sin(γ)
cos(β)sin(γ)    sin(α)sin(β)sin(γ)+cos(α)cos(γ)   cos(α)sin(β)sin(γ)-sin(α)cos(γ)
-sin(β)         sin(α)cos(β)                      cos(α)cos(β)

如果您唯一的选择是“必须从某个方向开始,然后在不引起任何 z 旋转的情况下更改为新方向”,则:

  • 找到会导致当前方向的矢量和旋转
  • 旋转回平坦方向
  • 然后使用上述方法旋转到新方向。
  • 沿着同一向量向外完全向后走会抵消旋转效果。

效果看起来有点像这个过程(红色:所需路径,蓝色:实际路径)

  • Object Moving
  • 自己的作品