Example #1
0
        // Update the filter for all body joints
        private void FilterBodyJoints(ref KinectInterop.BodyData bodyData, int bodyIndex, SmoothParameters tempSmoothingParams)
        {
            KinectManager manager    = KinectManager.Instance;
            int           jointCount = manager.GetJointCount();

            for (int jointIndex = 0; jointIndex < jointCount; jointIndex++)
            {
                // If not tracked, we smooth a bit more by using a bigger jitter radius
                // Always filter end joints highly as they are more noisy
                if (bodyData.joint[jointIndex].trackingState != KinectInterop.TrackingState.Tracked ||
                    jointIndex == (int)KinectInterop.JointType.FootLeft || jointIndex == (int)KinectInterop.JointType.FootRight ||
                    jointIndex == (int)KinectInterop.JointType.HandLeft || jointIndex == (int)KinectInterop.JointType.HandRight ||
                    jointIndex == (int)KinectInterop.JointType.HandtipLeft || jointIndex == (int)KinectInterop.JointType.HandtipRight ||
                    jointIndex == (int)KinectInterop.JointType.ThumbLeft || jointIndex == (int)KinectInterop.JointType.ThumbRight)
                //|| jointIndex == (int)KinectInterop.JointType.Head)
                {
                    tempSmoothingParams.jitterRadius       = smoothParameters.jitterRadius * 2.0f;
                    tempSmoothingParams.maxDeviationRadius = smoothParameters.maxDeviationRadius * 2.0f;
                }
                else
                {
                    tempSmoothingParams.jitterRadius       = smoothParameters.jitterRadius;
                    tempSmoothingParams.maxDeviationRadius = smoothParameters.maxDeviationRadius;
                }

                Vector3 jPosition = bodyData.joint[jointIndex].trackingState != KinectInterop.TrackingState.NotTracked ? bodyData.joint[jointIndex].position : Vector3.zero;
                bodyData.joint[jointIndex].position = FilterJoint(jPosition, bodyIndex, jointIndex, tempSmoothingParams);
            }

            bodyData.position = bodyData.joint[0].position;
        }
Example #2
0
        // averages the bodies in the list and returns the single merged body
        private KinectInterop.BodyData GetMergedBody(List <KinectInterop.BodyData> alCloseBodies, int bodyIndex, ref List <string> lostUsers)
        {
            int jointCount = (int)KinectInterop.JointType.Count;

            KinectInterop.BodyData mergedBody = new KinectInterop.BodyData(jointCount);

            for (int j = 0; j < jointCount; j++)
            {
                int maxTrackingState = GetBodyJointMaxState(alCloseBodies, j);
                CalcAverageBodyJoint(alCloseBodies, j, maxTrackingState, ref mergedBody);
            }

            mergedBody.liTrackingID = GetMergedBodyId(alCloseBodies, ref lostUsers);
            mergedBody.iBodyIndex   = bodyIndex;

            KinectInterop.JointData pelvisData = mergedBody.joint[0];
            mergedBody.bIsTracked = pelvisData.trackingState != KinectInterop.TrackingState.NotTracked;

            //Debug.Log(string.Format("MBody {0} Id: {1}, pos: {2}, rot: {3}", bodyIndex, mergedBody.liTrackingID, pelvisData.position, pelvisData.normalRotation.eulerAngles));

            mergedBody.kinectPos = pelvisData.kinectPos;
            mergedBody.position  = pelvisData.position;

            mergedBody.orientation      = pelvisData.orientation;
            mergedBody.normalRotation   = pelvisData.normalRotation;
            mergedBody.mirroredRotation = pelvisData.mirroredRotation;

            KinectInterop.CalcBodyJointDirs(ref mergedBody);

            return(mergedBody);
        }
Example #3
0
        /// <summary>
        /// Merges the user bodies, detected by the multiple sensors.
        /// </summary>
        public List <KinectInterop.BodyData> MergeUserBodies(ref ulong lastBodyFrameTime)
        {
            // get list of all bodies
            List <KinectInterop.BodyData> alAllBodies = GetAllBodiesList(ref lastBodyFrameTime);

            // build mergeable body sets
            List <List <KinectInterop.BodyData> > mergeableBodySets = new List <List <KinectInterop.BodyData> >();

            while (alAllBodies.Count > 0)
            {
                List <KinectInterop.BodyData> alCloseBodies = new List <KinectInterop.BodyData>();
                alCloseBodies.Add(alAllBodies[0]);
                alAllBodies.RemoveAt(0);

                FindOverlappingBodies(ref alCloseBodies, ref alAllBodies, MAX_DISTANCE_TO_CLOSE_BODY, mergeableBodySets.Count);
                mergeableBodySets.Add(alCloseBodies);
            }

            // merge the bodies
            List <KinectInterop.BodyData> alMergedBodies = new List <KinectInterop.BodyData>();

            List <string> lostUsers = new List <string>();

            lostUsers.AddRange(dictSensorUserIdToUserId.Keys);

            for (int i = 0; i < mergeableBodySets.Count; i++)
            {
                KinectInterop.BodyData mergedBody = GetMergedBody(mergeableBodySets[i], i, ref lostUsers);
                alMergedBodies.Add(mergedBody);
            }

            // clean up
            mergeableBodySets.Clear();
            mergeableBodySets = null;
            alAllBodies       = null;

            if (lostUsers.Count > 0)
            {
                foreach (string sensorUserId in lostUsers)
                {
                    if (dictSensorUserIdToUserId.ContainsKey(sensorUserId) && (Time.time - dictSensorUserIdToLastUsed[sensorUserId]) >= WAIT_TIME_BEFORE_REMOVAL)
                    {
                        dictSensorUserIdToUserId.Remove(sensorUserId);
                        dictSensorUserIdToFirstUsed.Remove(sensorUserId);
                        dictSensorUserIdToLastUsed.Remove(sensorUserId);

                        //Debug.Log("Removed lost sensor-user-id from dict: " + sensorUserId);
                    }
                }

                lostUsers.Clear();
                lostUsers = null;
            }

            return(alMergedBodies);
        }
Example #4
0
        // returns list of all bodies, tracked by all sensors
        private List <KinectInterop.BodyData> GetAllBodiesList(ref ulong lastBodyFrameTime, BoneOrientationConstraints boneConstraints)
        {
            List <KinectInterop.BodyData> alAllBodies = new List <KinectInterop.BodyData>();

            for (int s = 0; s < sensorDatas.Count; s++)
            {
                if (SINGLE_SENSOR_INDEX >= 0 && s != SINGLE_SENSOR_INDEX)
                {
                    continue;
                }

                KinectInterop.SensorData sensorData = sensorDatas[s];
                uint sensorBodyCount = sensorData.trackedBodiesCount;

                if (sensorBodyCount > 0 && sensorData.lastBodyFrameTime > lastBodyFrameTime)
                {
                    lastBodyFrameTime = sensorData.lastBodyFrameTime;
                }

                for (uint b = 0; b < sensorBodyCount; b++)
                {
                    KinectInterop.BodyData bodyData = new KinectInterop.BodyData((int)KinectInterop.JointType.Count);

                    sensorData.alTrackedBodies[b].CopyTo(ref bodyData);
                    bodyData.sensorIndex = s;

                    // filter orientation constraints
                    if (boneConstraints != null)
                    {
                        boneConstraints.Constrain(ref bodyData);
                    }

                    alAllBodies.Add(bodyData);
                }

                //break;
            }

            if (alAllBodies.Count > 0)
            {
                //Debug.Log("Found " + alAllBodies.Count + " total bodies.");
            }

            return(alAllBodies);
        }
Example #5
0
        //// Update the filter with a new frame of data and smooth.
        //public void UpdateFilter(ref KinectInterop.BodyData[] alTrackedBodies)
        //{
        //    if (!init)
        //    {
        //        // initialize with by-default parameters
        //        Init();
        //    }

        //    if (smoothingType == SmoothingType.None)
        //        return;

        //    SmoothParameters tempSmoothingParams = new SmoothParameters();
        //    tempSmoothingParams.smoothing = this.smoothParameters.smoothing;
        //    tempSmoothingParams.correction = this.smoothParameters.correction;
        //    tempSmoothingParams.prediction = this.smoothParameters.prediction;

        //    int bodyCount = alTrackedBodies != null ? alTrackedBodies.Length : 0;
        //    for (int bodyIndex = 0; bodyIndex < bodyCount; bodyIndex++)
        //    {
        //        if (alTrackedBodies[bodyIndex].bIsTracked)
        //        {
        //            FilterBodyJoints(ref alTrackedBodies[bodyIndex], /**bodyIndex*/ alTrackedBodies[bodyIndex].iBodyIndex, tempSmoothingParams);
        //        }
        //    }
        //}

        // Update the filter with a new frame of data and smooth.
        public void UpdateFilter(ref KinectInterop.BodyData bodyData)
        {
            if (!init)
            {
                // initialize with by-default parameters
                Init();
            }

            if (smoothingType == SmoothingType.None)
            {
                return;
            }

            SmoothParameters tempSmoothingParams = new SmoothParameters();

            tempSmoothingParams.smoothing  = smoothParameters.smoothing;
            tempSmoothingParams.correction = smoothParameters.correction;
            tempSmoothingParams.prediction = smoothParameters.prediction;

            if (bodyData.bIsTracked)
            {
                // get body index
                int bodyIndex = GetUserIndex(bodyData.liTrackingID);
                if (bodyIndex < 0)
                {
                    bodyIndex = GetFreeIndex();
                    if (bodyIndex >= 0)
                    {
                        history[bodyIndex].userId = bodyData.liTrackingID;
                    }
                    //Debug.Log("Created history for userId: " + history[bodyIndex].userId + ", index: " + bodyIndex + ", time: " + DateTime.UtcNow);
                }

                // filter
                if (bodyIndex >= 0)
                {
                    FilterBodyJoints(ref bodyData, bodyIndex, tempSmoothingParams);
                }
            }

            // free unused history
            //CleanUpUserHistory();
        }
        // Apply the orientation constraints
        public void Constrain(ref KinectInterop.BodyData bodyData)
        {
            KinectManager kinectManager = KinectManager.Instance;
            frameNum++;

            for (int i = 0; i < jointConstraints.Count; i++)
            {
                BoneOrientationConstraint jc = this.jointConstraints[i];

                if (jc.thisJoint == (int)KinectInterop.JointType.Pelvis || bodyData.joint[jc.thisJoint].normalRotation == Quaternion.identity)
                    continue;
                if (bodyData.joint[jc.thisJoint].trackingState == KinectInterop.TrackingState.NotTracked)
                    continue;

                int prevJoint = (int)KinectInterop.GetParentJoint((KinectInterop.JointType)jc.thisJoint);
                if (bodyData.joint[prevJoint].trackingState == KinectInterop.TrackingState.NotTracked)
                    continue;

                Quaternion rotParentN = bodyData.joint[prevJoint].normalRotation;
                //Quaternion rotDefaultN = Quaternion.identity;  // Quaternion.FromToRotation(KinectInterop.JointBaseDir[prevJoint], KinectInterop.JointBaseDir[jc.thisJoint]);
                //rotParentN = rotParentN * rotDefaultN;

                Quaternion rotJointN = bodyData.joint[jc.thisJoint].normalRotation;
                Quaternion rotLocalN = Quaternion.Inverse(rotParentN) * rotJointN;
                Vector3 eulerAnglesN = rotLocalN.eulerAngles;

                bool isConstrained = false;
                //string sDebug = string.Empty;

                for (int a = 0; a < jc.axisConstrainrs.Count; a++)
                {
                    AxisOrientationConstraint ac = jc.axisConstrainrs[a];
                    Quaternion rotLimited = rotLocalN;

                    switch (ac.consType)
                    {
                        case 0:
                            break;

                        case CT.LimA:
                            eulerAnglesN = LimitAngles(eulerAnglesN, ac.axis, ac.angleMin, ac.angleMax);
                            rotLimited = Quaternion.Euler(eulerAnglesN);
                            break;

                        case CT.LimST:
                            rotLimited = LimitSwing(rotLocalN, ac.axis, ac.angleMin);
                            rotLimited = LimitTwist(rotLimited, ac.axis, ac.angleMax);
                            break;

                        case CT.LimH:
                            float lastAngle = bodyData.joint[jc.thisJoint].lastAngle;
                            rotLimited = LimitHinge(rotLocalN, ac.axis, ac.angleMin, ac.angleMax, ref lastAngle);
                            bodyData.joint[jc.thisJoint].lastAngle = lastAngle;
                            break;

                        default:
                            throw new Exception("Undefined constraint type found: " + (int)ac.consType);
                    }

                    if (rotLimited != rotLocalN)
                    {
                        rotLocalN = rotLimited;
                        isConstrained = true;
                    }
                }

                //if (sDebug.Length > 0)
                //{
                //    if (debugText != null && jc.thisJoint == (int)KinectInterop.JointType.ElbowLeft)
                //    {
                //        //					debugText.text = sDebug;
                //    }

                //    Debug.Log(sDebug);
                //}

                if (isConstrained)
                {
                    rotJointN = rotParentN * rotLocalN;

                    Vector3 eulerJoint = rotJointN.eulerAngles;
                    Vector3 eulerJointM = new Vector3(eulerJoint.x, -eulerJoint.y, -eulerJoint.z);
                    Quaternion rotJointM = Quaternion.Euler(eulerJointM);

                    // put it back into the bone orientations
                    bodyData.joint[jc.thisJoint].normalRotation = rotJointN;
                    bodyData.joint[jc.thisJoint].mirroredRotation = rotJointM;
                }

            }
        }
Example #7
0
        // returns averaged position of a body joint in a list of bodies
        private void CalcAverageBodyJoint(List <KinectInterop.BodyData> alBodyList, int jointIndex, int maxTrackingState,
                                          ref KinectInterop.BodyData bodyData)
        {
            Vector3 avgJointPos    = Vector3.zero;
            Vector3 firstKinectPos = Vector3.zero;

            Quaternion avgJointRot = Quaternion.identity;
            Quaternion firstJointOri = Quaternion.identity;
            Quaternion firstJointRot = Quaternion.identity;
            float      x = 0f, y = 0f, z = 0f, w = 0f;

            float jointAvgCount = 0f;
            int   bodyCount     = alBodyList.Count;

            //bool bJointOnePassOnly = Array.Exists(_OnePassJoints, j => j == jointIndex);

            for (int i = 0; i < bodyCount; i++)
            {
                ////if (bJointOnePassOnly)
                //if (jointIndex == (int)KinectInterop.JointType.WristLeft)
                //{
                //    Debug.Log(string.Format("{0:F3} {1}: {2}_{3}, state: {4}, pos: {5}, rot: {6}", Time.time, (KinectInterop.JointType)jointIndex,
                //        alBodyList[i].sensorIndex, alBodyList[i].liTrackingID, alBodyList[i].joint[jointIndex].trackingState,
                //        alBodyList[i].joint[jointIndex].position, alBodyList[i].joint[jointIndex].mirroredRotation.eulerAngles));
                //}

                //if (SINGLE_SENSOR_INDEX >= 0 && alBodyList[i].sensorIndex != SINGLE_SENSOR_INDEX)
                //    continue;

                KinectInterop.TrackingState jointState = alBodyList[i].joint[jointIndex].trackingState;
                //if ((int)jointState == maxTrackingState)
                if (jointState != KinectInterop.TrackingState.NotTracked)
                {
                    Quaternion jointRot = alBodyList[i].joint[jointIndex].normalRotation;

                    if (avgJointPos == Vector3.zero)
                    {
                        firstKinectPos = alBodyList[i].joint[jointIndex].kinectPos;
                        firstJointOri  = alBodyList[i].joint[jointIndex].orientation;
                        firstJointRot  = jointRot;
                    }

                    if (jointIndex == 0)
                    {
                        //Debug.Log(string.Format("Body Id: {0}_{1}, pos: {2}, rot: {3}", alBodyList[i].sensorIndex, alBodyList[i].liTrackingID, alBodyList[i].joint[jointIndex].position, alBodyList[i].joint[jointIndex].normalRotation.eulerAngles));
                    }

                    float jointWeight = 1f; // jointState != KinectInterop.TrackingState.Inferred ? 1f : 0.5f;
                    avgJointPos += alBodyList[i].joint[jointIndex].position * jointWeight;

                    if (Quaternion.Dot(jointRot, firstJointRot) < 0f)
                    {
                        jointRot = new Quaternion(-jointRot.x, -jointRot.y, -jointRot.z, -jointRot.w);  // inverse the sign
                    }
                    if (jointWeight < 0.9f)
                    {
                        jointRot = Quaternion.Slerp(Quaternion.identity, jointRot, jointWeight);
                    }
                    x += jointRot.x; y += jointRot.y; z += jointRot.z; w += jointRot.w;

                    jointAvgCount += jointWeight; // (jointState != KinectInterop.TrackingState.Inferred ? 1f : 0.5f);

                    //if(bJointOnePassOnly)
                    //    break;
                }
            }

            if (jointAvgCount > 0)
            {
                float addDet = 1f / jointAvgCount;
                avgJointPos = avgJointPos * addDet;

                x *= addDet; y *= addDet; z *= addDet; w *= addDet;
                float lengthD = 1.0f / (w * w + x * x + y * y + z * z);
                x          *= lengthD; y *= lengthD; z *= lengthD; w *= lengthD;
                avgJointRot = new Quaternion(x, y, z, w);
            }

            KinectInterop.JointData jointData = bodyData.joint[jointIndex];

            jointData.trackingState = (KinectInterop.TrackingState)maxTrackingState;
            jointData.kinectPos     = firstKinectPos;
            jointData.position      = avgJointPos;

            jointData.orientation    = firstJointOri;
            jointData.normalRotation = avgJointRot;

            Vector3 mirroredRot = avgJointRot.eulerAngles;

            mirroredRot.y = -mirroredRot.y;
            mirroredRot.z = -mirroredRot.z;
            jointData.mirroredRotation = Quaternion.Euler(mirroredRot);

            bodyData.joint[jointIndex] = jointData;
        }