microsoft / Azure-Kinect-Sensor-SDK

A cross platform (Linux and Windows) user mode SDK to read data from your Azure Kinect device.
https://Azure.com/Kinect
MIT License
1.49k stars 618 forks source link

Body tracking - Joint information [question] #1414

Open AswinkarthikeyenAK opened 3 years ago

AswinkarthikeyenAK commented 3 years ago

Hi, I am using ubuntu 18.04
The joint body tracking frames shown in the kinect k4abt_simple_3d_viewer seems to be different compared to the joint data information shown in the documents. For instance, in the picture below, the frames of right hand is seen image

In the body tracking joint information from microsoft website, the frames of the right hand are different when compared with the data from the k4abt_simple_3d_viewer image image

If you compare the figures specifically looking at the the right hand, Y is in front and Z is Down in the documentation, but the data observed from k4abt_simple_3d_viewer for the right hand side, Y and Z are different.

I am not sure if i Understand this correctly, Can you please provide me with more information that would help me understand it better?

Thanks

Chris45215 commented 3 years ago

Seeing as someone has started the topic, it would be very helpful if the orientation image in the documentation could be updated so that it is more clear. Any axis that happens to be along the black line of the bone is hidden by the black line, which makes it a bit difficult to tell which joint that axis line is for. For example, in the torso, the X axes are covered by that black line, so it takes a moment to figure out that the X is pointing up, rather than downwards. This isn't too bad on the torso, but it is bad around the left shoulder because there are two "X"s between the figure's left clavicle and left shoulder, but I can't figure out what joint they are for.

I suggest fixing it by making the orientation markers bolder, so they can be seen even if the are 'behind' the bone.

diablodale commented 3 years ago

Hi @qm13. I'm blocked ๐Ÿงฑ on the lack of accurate joint orientation documentation. This issue and numerous others all highlight the lack of detail and correctness of the existing joint orientation doc at https://docs.microsoft.com/en-us/azure/kinect-dk/body-joints.

Here are a short list of errors and gaps. There may be more

In https://github.com/microsoft/Azure-Kinect-Sensor-SDK/issues/687 you wrote "You can implement a simple translation to covert to the legacy Kinect for Windows". This isn't true. No translate will transform an orientation from Kinect Azure -> kinect v2. There might be a transform or a rotation but never a translate. I request the sample C code to do such a transform. It should be simple as you wrote. ๐Ÿ˜‰

k4a_quaternion_t k4abt_orient_to_kfw2(k4a_quaternion_t k4a_quat) {
    // simple code
}

kfw2_pelvis = k4abt_orient_to_kfw2(k4abt_skeleton_t::joints[K4ABT_JOINT_PELVIS].orientation);

The output of this function for the pelvis should have an almost identical quaternion as if I used a Kinect for Windows (v2) and got the same root node pelvis. And this quaternion is in the same Kv2 camera space https://docs.microsoft.com/en-us/previous-versions/windows/kinect/dn785530(v=ieb.10)#camera-space

I tried 13 permutations (out of the 432 possible) of wxyz in both +/-. It is too many permutations to try by brute force. Uncountable numbers of composite quat rotations. Sample code doesn't help as its all for puppet tools. And the doc is unclear and in some cases wrong above. ๐Ÿ˜ฅ

knat commented 3 years ago

@diablodale, you can rotate the kinect quaternion to get what you want. To rotate a quaternion, multiply the quaternion with another quaternion.

Demo using DirectXMath:

//XMQuaternionRotationRollPitchYaw(XMConvertToRadians(-90/*90, 0, -90, try :)*/), XMConvertToRadians(90/*90, 0, -90, try :)*/), XMConvertToRadians(0/*90, 0, -90, try :)*/)) = { -0.5f, 0.5f, 0.5f, 0.5f };
static const XMVECTORF32 g_rotSpine = { -0.5f, 0.5f, 0.5f, 0.5f };//to get mirrored(think kinect as a mirror), invert the sign of w and one of x, y or z: { -0.5f, 0.5f, -0.5f, -0.5f }

static const XMVECTORF32 g_rotLeftArm ={/*try :)*/};
static const XMVECTORF32 g_rotLeftHand ={/*try :)*/};
static const XMVECTORF32 g_rotLeftHip = {/*try :)*/};
static const XMVECTORF32 g_rotLeftKnee = {/*try :)*/};
static const XMVECTORF32 g_rotLeftAnkle = {/*try :)*/};
static const XMVECTORF32 g_rotLeftFoot = {/*try :)*/};

static const XMVECTORF32 g_rotRightArm ={/*try :)*/};
...

inline static XMVECTOR XM_CALLCONV GetQuaternion(k4abt_joint_t const& joint) {
    auto const& qua = joint.orientation;
    return XMVectorSet(qua.wxyz.x, qua.wxyz.y, qua.wxyz.z, qua.wxyz.w);
}

XMVECTOR quaPELVIS = XMQuaternionMultiply(g_rotSpine, GetQuaternion(skeleton.joints[K4ABT_JOINT_PELVIS]));
XMVECTOR quaSPINE_NAVEL = XMQuaternionMultiply(g_rotSpine, GetQuaternion(skeleton.joints[K4ABT_JOINT_SPINE_NAVEL]));
...
XMVECTOR quaCLAVICLE_LEFT = XMQuaternionMultiply(g_rotLeftArm, GetQuaternion(skeleton.joints[K4ABT_JOINT_CLAVICLE_LEFT]));
XMVECTOR quaSHOULDER_LEFT = XMQuaternionMultiply(g_rotLeftArm, GetQuaternion(skeleton.joints[K4ABT_JOINT_SHOULDER_LEFT]));
...
diablodale commented 3 years ago

Hi. Unfortunately, rotating the quat is not enough. I've brute-forced one joint...the waist. I had to permutate the quat's 3 imaginary components and rotate it.

Rotation only moves the axes to align. What is missing is the rotations around those axes. For example, the waist joint on the Azure Kinect rotates around the Z axis and X follows the bone. The Kinect v1 and 2 rotates around the X axis and Y follows the bone. This makes it necessary to permutate and rotate.

I have to understand the global coordinate system (the well known Kinect v1 and v2) and the local coordinate system (mystery Azure Kinect). And from what I have so far discovered, the Azure Kinect local coordinate system changes on spine, each arm, and each legs. I can already see the permutation of quat imaginaries and the rotation changes for waist, left hip, right hip. I can't reuse my code for the waist. I have to brute force each joint again and have a giant switch() so I can permutate the imaginaries.

I've been coding Kinect solutions for 8 years. I can do it when I have enough documentation. Otherwise, I'm reverse-engineering and brute-forcing it. ๐Ÿ˜ข

The Azure Kinect team may not know how to do this. They used synthetic data to train their neural net. Puppet data in -> puppet data out, so they never needed to logic/analyze it and may treat it as a black box. This is very typical of neural net solutions. I could be wrong here but it matches a few related posts and years-delay not documenting it.

knat commented 3 years ago

Hi. We can get the following result, after rotating kinect quaternion, if body is in rest-pose(T-pose), EVERY bone orientation is +Y: 2 Call it rest-quaternion.

If body is not in rest-pose, bone orientation is: 3 Call it active-quaternion.

You can convert quaternion to Euler angles: https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

diablodale commented 3 years ago

Thanks for your post. I can see you want to assist, but I'm unclear what you are communicating in your last post. ๐Ÿคทโ€โ™€๏ธ๐Ÿ™‚ Kinect v1 and v2 "TPose" rotate joints on different axes than Kinect v3 (aka Azure Kinect). Kinect v1 and v2 are as your draw immediately above. Bone on Y. Rotation around X. Kinect v3 is probably bone on X. Probably rotation around Z. https://docs.microsoft.com/en-us/azure/kinect-dk/body-joints

My approach is brute force. I have 96 possibilities of quat coefficient permutations and sign changes. I prioritize sign changes using levi-civita first, then fallback to the remaining possibilities. I have no need to convert to Euler angles. That would add computation for no value, and introduces order of rotation and potentially gimbal lock. I think I can stay within quats and avoid changing rotation methods just to reverse-engineer. ๐Ÿคž

diablodale commented 3 years ago

Other inconsistences I've discovered

It is these types of technical details that are needed in the documentation ๐Ÿ˜Ÿ๐Ÿคนโ€โ™€๏ธ

danzeeeman commented 2 years ago

Hi. Unfortunately, rotating the quat is not enough. I've brute-forced one joint...the waist. I had to permutate the quat's 3 imaginary components and rotate it.

Rotation only moves the axes to align. What is missing is the rotations around those axes. For example, the waist joint on the Azure Kinect rotates around the Z axis and X follows the bone. The Kinect v1 and 2 rotates around the X axis and Y follows the bone. This makes it necessary to permutate and rotate.

I have to understand the global coordinate system (the well known Kinect v1 and v2) and the local coordinate system (mystery Azure Kinect). And from what I have so far discovered, the Azure Kinect local coordinate system changes on spine, each arm, and each legs. I can already see the permutation of quat imaginaries and the rotation changes for waist, left hip, right hip. I can't reuse my code for the waist. I have to brute force each joint again and have a giant switch() so I can permutate the imaginaries.

I've been coding Kinect solutions for 8 years. I can do it when I have enough documentation. Otherwise, I'm reverse-engineering and brute-forcing it. ๐Ÿ˜ข

The Azure Kinect team may not know how to do this. They used synthetic data to train their neural net. Puppet data in -> puppet data out, so they never needed to logic/analyze it and may treat it as a black box. This is very typical of neural net solutions. I could be wrong here but it matches a few related posts and years-delay not documenting it.

did you ever solve this I'm running into the same issues at the moment the

diablodale commented 2 years ago

Yes. I brute forced it over almost 3 weeks. It was tedious, grueling, grunt work caused by Microsoft's ongoing lack of documentation and API specs. ๐Ÿ˜•

Visual test harness, joint by joint, establishing base coord system for each joint (it changes), visually testing all quat permutation rotations for each joint, moving my own body for each perm and visually looking at the drawn effect to see the results. Iterating more than once to get all correct over the range of possible rotations. Sometimes pain in my left shoulder as this kind of repetitive movement is unnatural.

If anyone is interested, given the significant time and physical effort involved, I will gladly share my results for a fee + nda/license to not share the results further. Price will scale exponentially based on if the interested party makes depth sensors and/or operating systems. ๐Ÿ˜Š

danzeeeman commented 2 years ago

Yes. I brute forced it over almost 3 weeks. It was tedious, grueling, grunt work caused by Microsoft's ongoing lack of documentation and API specs. ๐Ÿ˜•

Visual test harness, joint by joint, establishing base coord system for each joint (it changes), visually testing all quat permutation rotations for each joint, moving my own body for each perm and visually looking at the drawn effect to see the results. Iterating more than once to get all correct over the range of possible rotations. Sometimes pain in my left shoulder as this kind of repetitive movement is unnatural.

If anyone is interested, given the significant time and physical effort involved, I will gladly share my results for a fee + nda/license to not share the results further. Price will scale exponentially based on if the interested party makes depth sensors and/or operating systems. ๐Ÿ˜Š

can I buy you a beer?

diablodale commented 2 years ago

I do like IPA ๐Ÿ˜‰. It would be 3 weeks 8 hours/day my hourly rate of IPAs ๐Ÿป More if you make sensors/os. I understand your interest. If you want to discuss specific terms, hit me up via email as listed in my profile. Naturally, Microsoft can generate this needed info dramatically cheaper given they own the spec and the code.

danzeeeman commented 2 years ago

Can someone at Microsoft address this so we don't have to pay highway robbery to some disgruntled German dev....

Chris45215 commented 2 years ago

I also did some joint normalization to solve this problem. Is the issue just that you want all the joints to have the same standard orientation?

If your project is open, or if you can share the aspects that my code would need to connect with, I can take a look and see what it would take for me to integrate it to your program. The price would be minimal (assuming it only takes me a few hours to integrate), or we could do an even trade if you can help with my own project. At the very least, I may be able to share the set of quaternion transformations that normalize it. Microsoft should have offered normalized rotations as an option in the SDK from the start, in my opinion.

On Wed, Sep 15, 2021, 1:31 PM Dan Moore @.***> wrote:

Can someone at Microsoft address this so we don't have to pay highway robbery to some disgruntled German dev....

โ€” You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/microsoft/Azure-Kinect-Sensor-SDK/issues/1414#issuecomment-920223680, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACAXNVGRLK2IHWZWV7RCPITUCDKATANCNFSM4TTLIBIQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

danzeeeman commented 2 years ago

Right now when I compute the relative joint orientations and apply them to parented nodes things are just wrong....

I have to flip the pelvis 90 X, 90 Z to get it upright.
I have to flip the hips 180 on an axis. I'm stuck on the clavicles trying to get the shoulders in the right place....when I ignore the nesting and just do everything in world pos/orientation everything works fine but I'm trying to use the skeleton data as a parented skeleton....

silencht commented 1 month ago

Until now, the coordinate system definition of Azure Kinect remains a mystery :(