3D相对角度和计算

3

我有一个以四元数形式表示旋转角度为r1的3D对象。 我使用局部欧拉角将其旋转:

transform.Rotate(new Vector3(0f, 15f, 0f), relativeTo: Space.Self); // right
transform.Rotate(new Vector3(-10f, -5f, 0f), relativeTo: Space.Self); // left up
transform.Rotate(new Vector3(0f, 0f, 90f), relativeTo: Space.Self); // 90 clockwise

现在我有一个旋转r2。如果我不知道应用了哪些角度,如何检索本地Y旋转总和15-5+0=10?可能无法准确获得该值(10),但你已经理解我的意思。也许我只能在本地r2空间中获取Y差异?


所以您已经通过四元数应用了r1,并且您想要在r1的基础上应用称为r2的第二个转换?如果是这种情况,您不需要获得r1,只需将r2应用于r1的结果即可。它们仅仅是复合的。所以 r3 = r2.r1 然后 T1 = r1.T0T2 = r2.T1,然后 T2 = r2.r1.T0,即 T2 = r3.T0 - Felix Castor
@FelixCastor,r1是起始旋转。r2是应用所有变换后的旋转。"你想在r1的基础上应用第二个变换" - 不,我想找到r1和r2之间本地(对于r2)Y角度差异。 - Vlad
see edit1 in my answer - Spektre
2个回答

6
我找到了一个可能的解决方案:

一个可能的解决方案:

        (r2 * Quaternion.Inverse(r1)).eulerAngles.Y

0

我仍然相信变换矩阵对你来说会是更好的方法。

如前面的问题所提到的,欧拉角并不适合你的目的,只会让事情变得混乱。但无论如何,你觉得这个怎么样:

P0=(0,0,0)
P1=(1,0,0) // or (0,0,1) y=0 !!!
A0=r2_localtoglobal(P0)
A1=r2_localtoglobal(P1)
B0=r2r1_localtoglobal(P0)
B1=r2r1_localtoglobal(P1)
A=A1-A0 // local r2 X axis direction in GCS (without r1)
B=B1-B0 // local r2r1 X axis direction in GCS (with r1)
angle=-acos((A.B)/(|A|.|B|)) // angle between A,B (but inverted because you wanted local angle)

我假设r1代表船,r2代表雷达。 [编辑1] 阅读您链接问题的编辑后,现在我终于清楚你想要什么了。
P0=(0,0,0)
P1=(1,0,0) // or (0,0,1) y=0 !!!
A0=r1_globaltolocal(P0)
A1=r1_globaltolocal(P1)
A=A1-A0   
angle=atanxy(A.x,A.z)
  • 其中r1是您的船只变换
  • 雷达变换与背景图像无关
  • atanxyatan2(y,x) = atan(y/x),但具有符号分解,因此它适用于整个< 0,2PI >区间

atan2,atanxy:

const double pi=M_PI;
const double pi2=2.0*M_PI;

double atanxy(double x,double y) // atan2 return < 0 , 2.0*M_PI >
        {
        int sx,sy;
        double a;
        const double _zero=1.0e-30;
        sx=0; if (x<-_zero) sx=-1; if (x>+_zero) sx=+1;
        sy=0; if (y<-_zero) sy=-1; if (y>+_zero) sy=+1;
        if ((sy==0)&&(sx==0)) return 0;
        if ((sx==0)&&(sy> 0)) return 0.5*pi;
        if ((sx==0)&&(sy< 0)) return 1.5*pi;
        if ((sy==0)&&(sx> 0)) return 0;
        if ((sy==0)&&(sx< 0)) return pi;
        a=y/x; if (a<0) a=-a;
        a=atan(a);
        if ((x>0)&&(y>0)) a=a;
        if ((x<0)&&(y>0)) a=pi-a;
        if ((x<0)&&(y<0)) a=pi+a;
        if ((x>0)&&(y<0)) a=pi2-a;
        return a;
        }

1
正如您所看到的,我使用了Unity3D标签,因此我不希望得到一个数学复杂的答案。 P0,P1 - 这是什么?我不明白您如何使用localtoglobal。然后,在“A = A1-A0”中,您是否正在减去旋转?您是否将两个四元数的x和z分量传递给atan函数?您提供了atan方法的源代码,而我只能使用System.Math.Atan/Atan2,但您没有提供更复杂的细节。 - Vlad
抱歉,我不是Unity用户,P0、P1、A0、A1、B0、B1、A和B都是三维点/向量(我认为这已经很明显了),而本地到全局意味着你必须在坐标系之间进行转换(使用你的Unity欧拉角数学函数)。这个答案并不复杂,如果你不理解它,你应该去了解一下3D空间中基本的向量数学。没有适当的知识,你很快就会在编程中遇到障碍(不要期望某个库中有适用于任何场合的数学函数,你总是需要自己编写代码)。 - Spektre
想法是比较旋转和未旋转的轴,并得到它们之间的角度。 - Spektre
这些原始的数学知识很令人钦佩,但是很遗憾它们与使用Unity没有任何关联。这就像当有人想知道“如何在Unity中弹跳物体!”时,你提供了碰撞的数学知识一样。嘿,你所要做的就是反转旋转,这很简单——旋转已经“内置”到Unity中了(当然——它是一个游戏引擎,如果不能移动物体,它就不存在了!) - Fattie

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