/// <summary>
        /// Update the skeleton model based on new data from Nuitrack
        /// </summary>
        /// <param name="newData">The new skeleton data</param>
        /// <returns>Indicator if interpolation was performed</returns>
        public bool Update(nt.Skeleton newData)
        {
            bool error = false;

            foreach (nuitrack.JointType jt in (nuitrack.JointType[])System.Enum.GetValues(typeof(nuitrack.JointType)))
            {
                //New position of the joint being processed
                Vector3 newJPos = newData.GetJoint(jt).Real.ToVector3();
                //Confidence of the new joint being looked at
                float newJConf = newData.GetJoint(jt).Confidence;

                if (DistanceTraveled(joints[jt], newJPos) > maxVelocity * Time.deltaTime)
                {
                    joints[jt] = new Joint(joints[jt].pos + Vector3.Normalize(newJPos - joints[jt].pos) * maxVelocity * Time.deltaTime, newJConf, jt);
                    error      = true;

                    if (log)
                    {
                        Debug.Log("Max joint velocity exceeded, interpolating");
                    }
                }
                else
                {
                    joints[jt] = new Joint(newJPos, newJConf, jt);
                }
            }

            return(error);
        }
    /// <summary>
    /// Get UserData from processed Nuitrack skeleton model after internal correction
    /// </summary>
    /// <param name="skel">Raw skeleton from Nuitrack</param>
    /// <returns>
    /// The UserData object computed from the Nuitrack skeleton and internal error correction models
    /// </returns>
    private UserData ProcessSkeleton(nt.Skeleton skel)
    {
        // Log Right Hand position
        nLog.Log("rElev", skel.GetJoint(nt.JointType.RightHand).Real.ToVector3().y);
        nLog.Log("rHorizX", skel.GetJoint(nt.JointType.RightHand).Real.ToVector3().x);
        nLog.Log("rHorizZ", skel.GetJoint(nt.JointType.RightHand).Real.ToVector3().z);

        // Update internal skeleton model
        sk.Update(skel);

        // Create vector from collar to torso
        Vector3 collarTorso = sk[nt.JointType.Torso].pos - sk[nt.JointType.RightCollar].pos;
        // Create vector from collar to shoulder
        Vector3 collarShoulder = sk[nt.JointType.RightShoulder].pos - sk[nt.JointType.RightCollar].pos;

        // Create normal vector for user's chest
        Vector3 bodyPlane = Vector3.Cross(collarTorso, collarShoulder);

        //Create vector from user's left shoulder to their right shoulder
        Vector3 shoulderVector = sk[nt.JointType.RightShoulder].pos - sk[nt.JointType.LeftShoulder].pos;

        // Get coordinates to use for the end of the user's arms based on whether the elbow or hand has higher tracking confidence
        Vector3 rightArmTip = GetPreferredJoint(sk[nt.JointType.RightHand], sk[nt.JointType.RightElbow]);
        Vector3 leftArmTip  = GetPreferredJoint(sk[nt.JointType.LeftHand], sk[nt.JointType.LeftElbow]);

        // Create vectors for each arm from shoulder to hand
        Vector3 rightArmVec = rightArmTip - sk[nt.JointType.RightShoulder].pos;
        Vector3 leftArmVec  = leftArmTip - sk[nt.JointType.LeftShoulder].pos;

        // Calculate user's arm angles and clip them
        float rightArmAngle = ClipSmallAngle(-Vector3.SignedAngle(rightArmVec, shoulderVector, bodyPlane));
        float leftArmAngle  = ClipSmallAngle(Vector3.SignedAngle(leftArmVec, -shoulderVector, bodyPlane));

        // Log arm angles
        nLog.Log("rAngle", rightArmAngle);
        nLog.Log("lAngle", leftArmAngle);

        // Clamp angles to -90 to 90
        leftArmAngle  = Mathf.Clamp(leftArmAngle, -90, 90);
        rightArmAngle = Mathf.Clamp(rightArmAngle, -90, 90);

        // Calculate maximum possible arm extensions based on the length of a users upper and lower arms
        float rightArmMaxExtension = Vector3.Magnitude(rightArmTip - sk[nt.JointType.RightElbow].pos) + Vector3.Magnitude(sk[nt.JointType.RightElbow].pos - sk[nt.JointType.RightShoulder].pos);
        float LeftArmMaxExtension  = Vector3.Magnitude(leftArmTip - sk[nt.JointType.LeftElbow].pos) + Vector3.Magnitude(sk[nt.JointType.LeftElbow].pos - sk[nt.JointType.LeftShoulder].pos);

        // Calculate current arm extensions as a percent of maximum extension
        float rightArmExtension = Vector3.ProjectOnPlane(rightArmVec, bodyPlane).magnitude / rightArmMaxExtension;
        float leftArmExtension  = Vector3.ProjectOnPlane(leftArmVec, bodyPlane).magnitude / LeftArmMaxExtension;

        // Create user data object with all the calculated values
        UserData userDataSample = new UserData(rightArmAngle, rightArmExtension, leftArmAngle, leftArmExtension);

        // Push the new user data object into the moving average
        av.PushSample(userDataSample);

        // Return the moving average of UserData
        return(av.GetAverage());
    }
 public bool Update(nt.Skeleton skel)
 {
     throw new NotImplementedException();
 }