Answered by:
Using Kinect to calculate angles between Human Body joints
Question

Hello,
So i'm trying to use kinect to get the joint angles of a human body .For example the angle between the Upper part of the arm and the Lower part ,so technically the elbow joint angle .I only need on axis angle ,so i only need the angle i would get if say the user stood Parallel to the camera.
Also attaching a rough sketch if what i want to achieve .
Thanks in Advance.
 Edited by ARtyomTOpchyan Thursday, September 8, 2011 1:35 PM
 Changed type ARtyomTOpchyan Thursday, September 8, 2011 1:35 PM
Answers

I'm pretty sure that you intend to use the left elbow with the left shoulder and the left wrist, but right now you're using the right elbow.
Also, to get the correct angle with elbow at origin and not the mirror image (although in this particular case it seems inconsequential) I think you'd want to do
Vector3 b1 =a3a1; Vector3 b2=a2a1;
Also, you need to normalize the dot product before doing the call to Math.Acos:AngleBetweenTwoVectors(Vector3.Normalize(b1), Vector3.Normalize(b2)).ToString();
Eddy
I'm here to help Proposed as answer by Eddy EscardoRaffo [MSFT] Thursday, September 8, 2011 10:21 PM
 Marked as answer by ARtyomTOpchyan Thursday, September 8, 2011 10:38 PM
All replies

Do you mean that you only need the elbow joint angle component in YZ plane? The Kinect SDK gives you positions of right wrist, left wrist, right elbow, left elbow, right shoulder and left shoulder as part of SkeletonData.Joints structure (in managed code, let me know if you're using C++ and I'll adapt examples).
Specifically, to get position of right wrist, you would do:
SkeletonData skeleton = <obtained from some skeleton frame>; Microsoft.Research.Kinect.Nui.Vector rightHand = skeleton.Joints[JointID.WristRight].Position;
so if you obtain positions of right wrist, elbow and shoulder in this way you should be able to compute angle by calculating the elbowwrist direction vector and the elbowshoulder direction vector and then using the standard vector dot product formula (http://en.wikipedia.org/wiki/Dot_product).Does that help?
Eddy
I'm here to help Proposed as answer by Eddy EscardoRaffo [MSFT] Thursday, September 8, 2011 6:47 PM

Thank you for the relpy.
I;m using C# and i know about the positions and also tried calculating the dot product the thing is that if i like stand perfectly straight in from of the Kinect the angle of my elbow should be like 180 degrees right ? But the dot product method yields different results .Or am i missing something here
Artyom Topchyan 

Something like this
Vector3 a1 = new Vector3(user.Joints[JointID.ElbowRight].Position.X, user.Joints[JointID.ElbowRight].Position.Y, user.Joints[JointID.ElbowRight].Position.Z); Vector3 a2 = new Vector3(user.Joints[JointID.ShoulderLeft].Position.X, user.Joints[JointID.ShoulderLeft].Position.Y, user.Joints[JointID.ShoulderLeft].Position.Z); Vector3 a3 = new Vector3(user.Joints[JointID.WristLeft].Position.X, user.Joints[JointID.WristLeft].Position.Y, user.Joints[JointID.WristLeft].Position.Z); Vector3 b1 =a1a3; Vector3 b2=a1a2; AngleBetweenTwoVectors(b1, b2).ToString(); public float AngleBetweenTwoVectors(Vector3 vectorA, Vector3 vectorB) { float dotProduct = 0.0f; dotProduct= Vector3.Dot( vectorA, vectorB ); return (float)Math.Acos(dotProduct); }
_
Artyom Topchyan
 Edited by ARtyomTOpchyan Thursday, September 8, 2011 9:11 PM

I'm pretty sure that you intend to use the left elbow with the left shoulder and the left wrist, but right now you're using the right elbow.
Also, to get the correct angle with elbow at origin and not the mirror image (although in this particular case it seems inconsequential) I think you'd want to do
Vector3 b1 =a3a1; Vector3 b2=a2a1;
Also, you need to normalize the dot product before doing the call to Math.Acos:AngleBetweenTwoVectors(Vector3.Normalize(b1), Vector3.Normalize(b2)).ToString();
Eddy
I'm here to help Proposed as answer by Eddy EscardoRaffo [MSFT] Thursday, September 8, 2011 10:21 PM
 Marked as answer by ARtyomTOpchyan Thursday, September 8, 2011 10:38 PM


First time posting here so first, thanks Eddy and others for your contributions. I've gained a lot from them.
I was wondering though if this method is the same way to calculate bone ZXY rotations for storage in the BVH file hierarchy. If not, please could anyone explain how. Thanks.


Flamme,
If you can point me to good documentation regarding BVH file hierarchy, I can read it and let you know whether this method for calculating angles corresponds to the angles expected in the BVH format. Otherwise, I have no idea.
Eddy
I'm here to help 
Hi Eddy,
Hadn't checked here for a while. Thanks for your reply. Here is a link explaining the structure. http://www.cmis.brighton.ac.uk/staff/alb14/ci219/lectures%20&%20tutorials/assets/BVH.rtf I gathered the rotational data are Euler values (xyz). Please go through looking forward to your take on it. Thanks.
Fllamme.
 Edited by Flamme Saturday, September 24, 2011 12:49 AM

It looks like you should be able to obtain a BVH kind of representation from the data provided by kinect, but you'd have to calculate the rotations yourself. The code above will only give you angle between two vectors that correspond to adjacent jointtojoint connections, and to obtain separate values for X vs Y vs Z rotation angles for each joint you would need to calculate angles of rotation against more than just one reference vector.
It's basically the same math, but with more components, and also keeping in mind that BVH structure is hierarchical.
Eddy
I'm here to help 
Hey Eddy,
I was looking at your response and had a question. How would you calculate the angles of rotation against more than one reference vector? Also, would you just need to calculate it against the all other joints in the hierarchy? All your help would be greatly appreciated!
Stephen

Hi,
i had the same problem. Thanks for the help.
I want to Display the resulting angle next to my Videoframe. How can I do this? So that the angle ist displayed for every frame that kinect delivers. (no saving so far, just displaying).
public float AngleBetweenTwoVectors(Vector3 b1, Vector3 b2) { AngleBetweenTwoVectors(Vector3.Normalize(b1), Vector3.Normalize(b2)).ToString(); float dotProduct = 0.0f; dotProduct = Vector3.Dot(b1, b2); double OUT= Math.Acos(dotProduct); return (float)Math.Acos(dotProduct); }
In my case its "OUT" what should be displayed next to the Videoframe.THANKS =)

Hey there..... i have tried to get the depth data and it worked fine.... but now i want to find out the angles between the joints... i'm a beginner in this regard...any detailed explanation would be highly grateful.
and also... is vector3 some kind of basic function ?? or do we have to assign a particular object for every angle we calculate ?
