Though I did not see your code or how you realized the person-tracking with overlaid skeleton, I recommend you reading the post series from Mike Taulty: http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2014/11/04/kinect-for-windows-v2-sdk-hello-custom-gesture-world-part-3.aspx (this link is the 3rd post of this series, you find the links to #1 and #2 at the very top).
While he uses the GestureBuilder Beta to track the skeleton movements, for me this was a great starting point to get things running - especially speaking of the KINECT setup, event listeners etc., to get a feel of how the KINECT 2 gets its frames and gets hooked up in c# code. In part 2 he fills a control in his WPF application with a color, depending on how much the recorded gestures progress was detected, I think this could partly answer your question regarding a "live variable" on a screen.
Once you followed the tutorial and identified the relevant code parts for you, you realize you can (strictly speaking) throw away the OnGestureFrameArrived functionality, as you will need to modify the OnBodyFrameArrived method. In here you check for a trackedBody, if one is found, you can access its Joints and calculate their angle. I wrote the result to a console-window for debugging purposes, so finally you would write this result to a variable which is hooked up with a GUI element that display it.
public void OnBodyFrameArrived(object sender, BodyFrameArrivedEventArgs e)
{
using (var frame = e.FrameReference.AcquireFrame())
{
if (frame != null)
{
frame.GetAndRefreshBodyData(this.bodies);
var trackedBody = this.bodies.Where(b => b.IsTracked).FirstOrDefault();
if (trackedBody != null)
{
List<Joint> myJoints = new List<Joint>();
myJoints.Add(trackedBody.Joints[JointType.FootLeft]);
myJoints.Add(trackedBody.Joints[JointType.AnkleLeft]);
myJoints.Add(trackedBody.Joints[JointType.KneeLeft]);
if (myJoints.TrueForAll(x => x.TrackingState == TrackingState.Tracked))
{
Vector3D KneeLeft = new Vector3D(trackedBody.Joints[JointType.KneeLeft].Position.X, trackedBody.Joints[JointType.KneeLeft].Position.Y, trackedBody.Joints[JointType.KneeLeft].Position.Z);
Vector3D AnkleLeft = new Vector3D(trackedBody.Joints[JointType.AnkleLeft].Position.X, trackedBody.Joints[JointType.AnkleLeft].Position.Y, trackedBody.Joints[JointType.AnkleLeft].Position.Z);
Vector3D FootLeft = new Vector3D(trackedBody.Joints[JointType.FootLeft].Position.X, trackedBody.Joints[JointType.FootLeft].Position.Y, trackedBody.Joints[JointType.FootLeft].Position.Z);
Console.WriteLine("#1: " + AngleBetweenTwoVectors(AnkleLeft - KneeLeft, AnkleLeft - FootLeft));
}
}
else
{
this.OnTrackingIdLost(null, null);
}
}
}
}
public double AngleBetweenTwoVectors(Vector3D vectorA, Vector3D vectorB)
{
double dotProduct = 0.0;
vectorA.Normalize();
vectorB.Normalize();
dotProduct = Vector3D.DotProduct(vectorA, vectorB);
return (double)Math.Acos(dotProduct) / Math.PI * 180;
}
TLDR-version: depending on how you handle your acquired kinect frames, you need to identify the correct event in your code, where a tracked body is found in a frame, in there you can look for the states of the different body joints and calculate the angles.
Further, if you want you can send me your code and I can try to hook this up for you, since your code would also be of interest to me.