Kinect SDK - 将旋转角度按度数进行转换

3

我对Kinect开发相对较新,正在尝试构建一个组件,允许旋转Kinect关节。其目的是在捕获后手动“修复”任何骨架数据,当骨架开始跳动时。

我使用helix toolkit在3D空间中显示Kinect骨架。可以在任何给定点暂停骨架流并查看BoneRotations对象中保存的绝对旋转和分层旋转的矩阵值。

我创建了三个滑块,代表X轴、Y轴和Z轴。我已将它们的最小/最大值设置为与要操作的骨骼自然运动相关的值(例如,在Y轴上,肩膀不会移动超过约40度)。以右肩(右侧)关节为例,我想能够在每个轴上应用旋转,以便我可以在3D空间中更改骨头的位置。我相信与此类操作相关的术语是正向运动学。

我的问题是:

a)Kinect SDK为关节提供绝对矩阵和分层矩阵。我应该查看哪一个来进行操作?

b)四元数比矩阵提供什么信息?

c)如何使用4x4矩阵信息找到X轴、Y轴和Z轴的角度(以度或弧度为单位)?

d)我已经看到了如何通过类似于以下计算来乘法转换3x3矩阵:

    Matrix3X3 matrixx = new Matrix3X3();
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            matrixx.elements[(i * 3) + j] = ((R2.elements[i * 3] * R1.elements[j]) + (R2.elements[(i * 3) + 1] * R1.elements[3 + j])) + (R2.elements[(i * 3) + 2] * R1.elements[6 + j]);
        }
    }
    return matrixx;

如何转换Kinect SDK给出的4x4矩阵?

更具体地说,我能否在每个轴上转换4x4矩阵,以便我可以为每个轴设置滑块?那么如何应用10度的X轴旋转?我已经看到过对3x3矩阵进行旋转的操作如下:

    public static Matrix3D NewRotateAroundX(double radians)
    {
        var matrix = new Matrix3D();
        matrix._matrix[1, 1] = Math.Cos(radians);
        matrix._matrix[1, 2] = Math.Sin(radians);
        matrix._matrix[2, 1] = -(Math.Sin(radians));
        matrix._matrix[2, 2] = Math.Cos(radians);
        return matrix;
    }
    public static Matrix3D NewRotateAroundY(double radians)
    {
        var matrix = new Matrix3D();
        matrix._matrix[0, 0] = Math.Cos(radians);
        matrix._matrix[0, 2] = -(Math.Sin(radians));
        matrix._matrix[2, 0] = Math.Sin(radians);
        matrix._matrix[2, 2] = Math.Cos(radians);
        return matrix;
    }
    public static Matrix3D NewRotateAroundZ(double radians)
    {
        var matrix = new Matrix3D();
        matrix._matrix[0, 0] = Math.Cos(radians);
        matrix._matrix[0, 1] = Math.Sin(radians);
        matrix._matrix[1, 0] = -(Math.Sin(radians));
        matrix._matrix[1, 1] = Math.Cos(radians);
        return matrix;
    }

提前感谢您的帮助!

1个回答

2
这是多个问题,你可能需要将它们拆分并分别提问。
a)我没有使用过Kinect,但通常情况下,绝对位置是相对于世界空间的,层级关系是相对于父级的。大多数时候,您想要移动一个关节相对于其父级。
b)这个问题问反了。四元数表示一个轴和绕该轴旋转的旋转,矩阵可以存储此变换以及许多其他类型,包括比例、平移、扭曲、投影等。
c)矩阵的前3行的前3个元素给出每个轴,即X、Y和Z(再次取决于您正在使用哪个空间,世界空间或父级空间)。提取这些,选择您所需的2个轴,并搜索“任意两个三维线之间的夹角”(它是它们之间点积的反余弦)。
d) 使用正确的算法取决于许多因素,有一种“正确”的方法,还有很多其他(更快)的方法,如果您可以保证矩阵始终遵循某些属性,如仿射等,则这些方法也可以正常工作。 维基百科有一个关于矩阵乘法的页面,或者您可以阅读我在将近20年前写的一篇旧文章,其中包含代码。 后者还应该帮助解释一些它们的工作原理,并可能向您展示如何执行其他一些您要做的事情。

谢谢你的回复,马克。答案A很有道理。问题B->我知道你没有真正使用过Kinect SDK,但它提供了四元数,所以我不明白它包含什么。它的旋转信息基于哪个轴?(可能只是我的理解不足)。问题C->我想我可以解决这个问题,谢谢。问题D->是时候开始阅读和理解了! :-) - Rob McCabe
有很多教程可以解释四元数,比我在这里能讲的更详细的好教程是http://www.cprogramming.com/tutorial/3d/quaternions.html。四元数由4个组件(XYZW)组成,通常用于旋转,即围绕线P1=<0,0,0>和P2=<X,Y,Z>旋转点并将其旋转W弧度。正如该文章所示,您可以将四元数转换为矩阵,尽管您不能总是将矩阵转换为四元数,因为它可能具有其他内容,例如平移等。 - Mark Feldman
这一切引出了一个问题:“为什么首先要使用四元数?” 四元数具有与矩阵相同的数学运算,但如果您只处理旋转,则四元数数学往往会更容易且更快。话虽如此,我作为一名3D图形程序员已经工作了16年,除非需要从其他地方导入它们(就像您现在正在做的那样),否则并没有真正使用它们。如果您有一个好的矩阵库,并且您的应用程序不是时间关键型的,则只需将它们转换为矩阵,并对所有内容使用常规矩阵运算,这样您将节省很多麻烦。 - Mark Feldman
谢谢你的帮助,马克! - Rob McCabe

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