在本文中,将探讨一个较为复杂的主题:如何测量关节在每个轴(X、Y、Z)上的取向。测量取向值并不简单,因为它需要一定的数学知识。不过别担心!阅读完本文后,将能够使用一行C#代码计算每个关节的取向!听起来不错吧?让开始吧。
要运行本文提供的代码和示例,需要以下条件:
Kinect读取关节取向值作为四元数。四元数是一组4个值:X、Y、Z和W。Kinect SDK将四元数封装到一个名为Vector4的结构中。需要将这个四元数(Vector4)转换成一组3个数值。使用取向四元数,可以计算关节围绕X、Y和Z轴的旋转。
围绕X轴的旋转称为俯仰角。以下是如何测量它的方法:
public static double Pitch(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.X + quaternion.Y * quaternion.Z);
double value2 = 1.0 - 2.0 * (quaternion.X * quaternion.X + quaternion.Y * quaternion.Y);
double roll = Math.Atan2(value1, value2);
return roll * (180.0 / Math.PI);
}
围绕Y轴的旋转称为偏航角。以下是如何测量它的方法:
public static double Yaw(this Vector4 quaternion)
{
double value = 2.0 * (quaternion.W * quaternion.Y - quaternion.Z * quaternion.X);
value = value > 1.0 ? 1.0 : value;
value = value < -1.0 ? -1.0 : value;
double pitch = Math.Asin(value);
return pitch * (180.0 / Math.PI);
}
围绕Z轴的旋转称为翻滚角。以下是如何测量它的方法:
public static double Roll(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.Z + quaternion.X * quaternion.Y);
double value2 = 1.0 - 2.0 * (quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z);
double yaw = Math.Atan2(value1, value2);
return yaw * (180.0 / Math.PI);
}
以下是完整的代码。只需要将以下C#文件导入Kinect项目中。
using System;
using Microsoft.Kinect;
namespace LightBuzz.Vitruvius
{
public static class JointOrientationExtensions
{
public static double Pitch(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.X + quaternion.Y * quaternion.Z);
double value2 = 1.0 - 2.0 * (quaternion.X * quaternion.X + quaternion.Y * quaternion.Y);
double roll = Math.Atan2(value1, value2);
return roll * (180.0 / Math.PI);
}
public static double Yaw(this Vector4 quaternion)
{
double value = 2.0 * (quaternion.W * quaternion.Y - quaternion.Z * quaternion.X);
value = value > 1.0 ? 1.0 : value;
value = value < -1.0 ? -1.0 : value;
double pitch = Math.Asin(value);
return pitch * (180.0 / Math.PI);
}
public static double Roll(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.Z + quaternion.X * quaternion.Y);
double value2 = 1.0 - 2.0 * (quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z);
double yaw = Math.Atan2(value1, value2);
return yaw * (180.0 / Math.PI);
}
}
}
然后在主C#文件中,导入以下命名空间:
using LightBuzz.Vitruvius;
最后,指定想要测量取向的关节,并调用Roll、Pitch和Yaw方法:
var orientation = body.JointOrientations[JointType.ElbowLeft].Orientation;
var rotationX = orientation.Pitch();
var rotationY = orientation.Yaw();
var rotationZ = orientation.Roll();
测量人体关节的旋转并不是一件容易的事情。不幸的是,Kinect并没有为提供头部、手部和脚部的取向值。这些关节没有“父”关节,因此很难准确测量它们的取向。其余关节的取向精度相当好。支持的关节如下: