计算旋转以查看一个三维点?

12
我需要计算一个3D对象朝向任意3D点时的两个角度(偏航角和俯仰角)。这些旋转被称为“欧拉”旋转,因为在第一次旋转后(假设基于下面图片的Z轴),Y轴也会随着物体一起旋转。
这是我正在使用的代码,但它没有完全工作。当在地面平面上(Y = 0)时,物体正确地旋转以朝向该点,但是当我将该点向上移动到Y轴时,旋转看起来不正确。
// x, y, z represent a fractional value between -[1] and [1]
// a "unit vector" of the point I need to rotate towards

yaw = Math.atan2( y, x )
pitch = Math.atan2( z, Math.sqrt( x * x + y * y ) )
你知道如何计算给定一个点的2个欧拉角吗?
下面的图片展示了我的旋转方式,这些是我需要计算的角度。(唯一的区别是我按照X、Y、Z的顺序旋转物体而不是Z、Y、X)

pic

enter image description here


这是我的坐标系。
  • 坐标系为x向右,y向下,z向远处
  • 一个对象默认位于(0,0,1),即朝向后方
  • 旋转顺序为X、Y、Z,其中绕X轴的旋转是俯仰角,Y轴是偏航角,Z轴是滚转角

my system


当你说“将物体向上移动在Y轴上”,你是指“将点向上移动在Y轴上”吗?旋转之前物体面向哪个方向? - Beta
@Beta - 是的,这就是我的意思。在旋转之前,该对象面朝后方,就像站在桌子上一样。 - Robin Rodricks
你好@Robinicks,能告诉我你在哪里拍的这张照片吗?图片链接为http://i53.tinypic.com/33lo6jp.jpg。 - Gennaro Arguzzi
@GennaroArguzzi - 我是用Adobe Flash设计的那个图形。 - Robin Rodricks
抱歉给@Robinicks带来了麻烦。我向您保证,第一张图片是从一本书中摘取的,因为我在幻灯片上有完整的图片(您的图片只是关于局部旋转的一半图像,而我的图片则涉及全局和局部旋转)。请看这个链接http://s000.tinyupload.com/index.php?file_id=83705559891752145583 - Gennaro Arguzzi
显示剩余2条评论
4个回答

15

以下是我的工作假设:

  • 坐标系(x,y,z)是这样的,即正x在右边,正y向下,而z则是剩余方向。特别是,y = 0是地面平面。
  • 一个面向(0,0,1)的位于(0,0,0)处的对象正在被转向面向(x,y,z)。
  • 为了实现这一点,将绕x轴旋转一次,然后再绕y轴旋转一次。最后,绕z轴旋转一次以使物体竖直。

(术语偏航、俯仰和翻滚可能令人困惑,因此我希望避免使用它,但大致上对应关系是 x=俯仰,y=偏航,z=翻滚。)

基于这个设置,以下是我解决您的问题的尝试:

rotx = Math.atan2( y, z )
roty = Math.atan2( x * Math.cos(rotx), z )
rotz = Math.atan2( Math.cos(rotx), Math.sin(rotx) * Math.sin(roty) )

希望这个答案的符号是正确的。我认为最简单的修正符号的方法是通过试错。确实,您似乎已经正确地处理了rotxroty上的符号——包括与z有关的微妙问题,所以您只需要修正rotz上的符号。

我预计这可能会比较复杂(可能取决于你处于哪个八分之一空间),但在说它错误之前,请尝试几种可能性。祝好运!


这是最终适用于我自己的代码。

我注意到当物体从任何前面的象限(正Z)移动到任何后面的象限时,会出现一个“翻转”效果。在前面的象限中,物体的前面总是面向该点。在后面的象限中,物体的后面总是面向该点。

这段代码纠正了翻转效应,使物体的前面始终面向该点。我通过试错遇到了它,所以我不太清楚发生了什么!

 rotx = Math.atan2( y, z );
 if (z >= 0) {
    roty = -Math.atan2( x * Math.cos(rotx), z );
 }else{
    roty = Math.atan2( x * Math.cos(rotx), -z );
 }

这里有一个我不理解的误解。你说如果对象在y=0处,你的代码可以工作,但我无法理解为什么会这样。在这种情况下,您计算yaw=0但pitch!=0,这似乎不正确。(这就是为什么我问z是否是上/下)。有什么想法吗? - A. Rex
是的,它有效,因为我的物体与其面向的点有一定距离,并且真正改变的角度只有偏航角(绕Y轴旋转,因此物体在水平方向上旋转以面向位于地面平面上的点)。我有没有说什么让人困惑的话? - Robin Rodricks
1
@Braineeee:Stack Overflow网站已经上线8年了。你现在正在评论一个7年前提出的问题,该问题最后一次活跃是在6年前。 - A. Rex
这对答案的有效性有什么影响吗? - user2213764
这很适用于如果你的坐标中有一个是0, 0, 0,但如果你有两个三维坐标呢? - MmBaguette
显示剩余6条评论

7

Rich Seller的答案展示了如何将一个点从一个3D坐标系旋转到另一个坐标系,给出了描述两个坐标系之间旋转的一组欧拉角。

但是听起来你在问另外一件事:

你有:一个点的3D坐标

你想要:一组欧拉角

如果这就是你所问的,那么你没有足够的信息。要找到欧拉角,你需要至少两个点的坐标,在两个坐标系中都有,以确定从一个坐标系到另一个坐标系的旋转。

你还应该知道欧拉角可能会产生歧义:Rich的答案假设旋转应用于Z、然后X'、然后Z',但这并不是标准化的。如果你必须与其他使用欧拉角的代码进行交互,你需要确保你使用相同的约定。

你可能想考虑使用旋转矩阵或四元数而不是欧拉角。


你没有足够的信息。我不是已经描述了在三维空间中的两点吗?第一个点可以是任何东西,而第二个点是0,0,0...所以我想要测量这两个点之间按照顺序XYZ的欧拉旋转。 - Robin Rodricks
请考虑更新您的答案,因为我已编辑了我的问题并添加了500美元的赏金。 - Robin Rodricks

3
这个系列的旋转将给你想要的结果:
  1. 关于X:0
  2. 关于Y:atan2(z,x)
  3. 关于Z:atan2(y,sqrt(x * x + z * z))
除非您首先定义如何使用“roll”,“pitch”和“yaw”这些术语,否则我无法告诉您它们是什么。您没有按照标准方式使用它们。 编辑:
好的,请尝试以下内容:

  1. 关于X:-atan2(y,z)
  2. 关于Y:atan2(x,sqrt(y * y + z * z))
  3. 关于Z:0

@Beta - 感谢您的回答。请查看我编辑后的问题,了解我的确切旋转系统 - 我不是真正需要俯仰/偏航,而是需要旋转X和旋转Y(请参见我的图片以了解我的意思)。 - Robin Rodricks
我假设x、y、z是指我试图旋转的方向的单位向量? - Robin Rodricks
我尝试了你的解决方案,但出于某些原因它没有起作用。由于 Rex 的答案已经99%的时间有效,所以太累了无法弄清楚为什么。非常感谢!继续保持好工作。 - Robin Rodricks
1
我认为我知道原因:您的图表是错误的。 - Beta
那太刻薄了,而且你猜怎么着,我的图表是正确的,因为Rex找出了正确的答案。看看最终为我工作的更新代码,它与你的相似,毫无疑问,但它仍然是有效的。 - Robin Rodricks
我曾经遇到过类似的问题,这个方法对我很有效。(只需要稍作调整。) - Roman Horváth

-2
谈到轴的旋转,我认为第三步应该是绕Y''轴旋转X'-、Y''-和Z'-轴。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接