【问题标题】:JavaFX 8 Transform to pitch, yaw and roll rotation anglesJavaFX 8 转换为俯仰、偏航和滚动旋转角度
【发布时间】:2015-06-13 09:32:29
【问题描述】:

实现this thread 的答案我有这段代码可以将 deltayaw、deltaroll 和 deltapitch 角度转换为一个角度并围绕它旋转一个节点。作为参数的角度是角度的瞬间变化,因为给出整个角度会忽略方向的变化。

    public static void matrixRotate(Group n, double deltaroll, double deltapitch, double deltayaw){    
    double A11 = Math.cos(deltaroll)*Math.cos(deltayaw);
    double A12 = Math.cos(deltapitch)*Math.sin(deltaroll)+Math.cos(deltaroll)*Math.sin(deltapitch)*Math.sin(deltayaw);
    double A13 = Math.sin(deltaroll)*Math.sin(deltapitch)-Math.cos(deltaroll)*Math.cos(deltapitch)*Math.sin(deltayaw);
    double A21 =-Math.cos(deltayaw)*Math.sin(deltaroll);
    double A22 = Math.cos(deltaroll)*Math.cos(deltapitch)-Math.sin(deltaroll)*Math.sin(deltapitch)*Math.sin(deltayaw);
    double A23 = Math.cos(deltaroll)*Math.sin(deltapitch)+Math.cos(deltapitch)*Math.sin(deltaroll)*Math.sin(deltayaw);
    double A31 = Math.sin(deltayaw);
    double A32 =-Math.cos(deltayaw)*Math.sin(deltapitch);
    double A33 = Math.cos(deltapitch)*Math.cos(deltayaw);

    double d = Math.acos((A11+A22+A33-1d)/2d);
    if(d!=0d){
        double den=2d*Math.sin(d);
        Point3D p= new Point3D((A32-A23)/den,(A13-A31)/den,(A21-A12)/den);
        Rotate r = new Rotate();
        r.setAxis(p);
        r.setAngle(Math.toDegrees(d));
        n.getTransforms().add(r);
        Transform all = n.getLocalToSceneTransform();
        n.getTransforms().clear();
        n.getTransforms().add(all);               
    }
}

(我使用旋转是因为我需要始终围绕原点而不是中心旋转对象)

现在这产生了一个问题,因为我不再能够获得实际的俯仰角、滚动角和偏航角。

我以前是这样跟踪它们的(不考虑方向的变化):

roll +=deltaroll;
pitch += deltapitch;
yaw += deltayaw;

后来我想出了这个,它更准确一点,但是如果没有直接修改角度(插入在 n.getTransforms().add(all) 之后),则不会跟踪发生的变化在主 sn-p):

roll+= Math.toDegrees(d)*((A32-A23)/den);
pitch += Math.toDegrees(d)*((A13-A31)/den);
yaw += Math.toDegrees(d)*((A21-A12)/den);  

我一直在寻找解决方案,发现 this answer 应该给出最终变换的角度,但我无法让它适用于所有角度。

double xx = n.getLocalToSceneTransform().getMxx();
double xy = n.getLocalToSceneTransform().getMxy();
double roll = Math.atan2(-xy, xx);

我再次尝试获得的是相对于场景的坐标系统的全角度(由不同方向的增量角度进行的变换合成)。我在这方面真的很糟糕,所以所有的帮助都会很棒。

【问题讨论】:

    标签: matrix 3d rotation javafx-8


    【解决方案1】:

    如果你想得到经过几次旋转后任意阶段的俯仰角、偏航角和滚动角,可以从3D模型的变换矩阵中得到。

    如果你看看几次旋转后的变换矩阵:

    Transform T = model3D.getLocalToSceneTransform();
    System.out.println(T);
    

    你会看到这样的东西:

    Transform [
            0.9034731871219395, -0.4260296991535005, -0.04727468234587054, 1.4044414829046357
            0.3743586809560477, 0.837958815679334, -0.39709016761704913, 0.5234811188037405
            0.2087864414768669, 0.3410626315861443, 0.9165612381019399, -1.1277640590168572
        ]
    

    如果你想要角度,你只需要将这个矩阵与这个answer中的这个矩阵进行比较:

    正如您已经说过的,要获得滚动角,您可以使用 T.getMxx()T.getMyx()

    double roll = Math.atan2(-T.getMyx(),T.getMxx());
    

    现在,对于音高,您可以以相同的方式使用T.getMzy()T.getMzz()

    double pitch = Math.atan2(-T.getMzy(),T.getMzz());
    

    最后,对于偏航,使用T.getMzx()T.getMzy()T.getMzz()

    double yaw = Math.atan2(T.getMzx(),Math.sqrt(T.getMzy()*T.getMzy()+T.getMzz()*T.getMzz()));
    

    这将为上述矩阵提供您正在寻找的角度(以弧度为单位):

    roll: -0.39281984604895126
    pitch: -0.356235553820928
    yaw: 0.21033388848106072
    

    【讨论】:

    • 好吧,这种工作,但角度似乎被限制在 -90 到 90 度之间,并在达到该边界后开始反转。这有点奇怪,因为 atan2 应该处理这个问题。
    • 我无法确定,但问题可能在于您在matrixRotate() 上获得旋转角度的方式。在某些极端情况下,特征值方法会给您带来一些故障......
    • 现在我已经对其进行了更多测试,似乎只有偏航计算关闭,俯仰和横滚在 180 到 -180 之间工作正常。我的猜测是平方根消除了一半的结果?也许我可以处理异常......
    • 还有一件事,似乎是这样:double yaw = Math.atan2(T.getMzx(),Math.sqrt(T.getMzy()*T.getMzy()+T.getMzz ()*T.getMzz()));与 double yaw = Math.toDegrees(Math.asin(T.getMxz()));
    • 当然,正如您在矩阵图上看到的那样,您可以从Mxz 获得角度,但我认为使用tan2 覆盖更多角落情况会更好。
    猜你喜欢
    • 2013-02-18
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    相关资源
    最近更新 更多