How to move a kinect skeleton to another position
Asked Answered
R

1

8

I am working on a extension method to move one skeleton to a desired position in the kinect field os view.

My code receives a skeleton to be moved and the destiny position, i calculate the distance between the received skeleton hip center and the destiny position to find how much to move, then a iterate in the joint applying this factor. My code, actualy looks like this.

public static Skeleton MoveTo(this Skeleton skToBeMoved, Vector4 destiny)
    {
        Joint newJoint = new Joint();

        ///Based on the HipCenter (i dont know if it is reliable, seems it is.)
        float howMuchMoveToX = Math.Abs(skToBeMoved.Joints[JointType.HipCenter].Position.X - destiny.X);
        float howMuchMoveToY = Math.Abs(skToBeMoved.Joints[JointType.HipCenter].Position.Y - destiny.Y);
        float howMuchMoveToZ = Math.Abs(skToBeMoved.Joints[JointType.HipCenter].Position.Z - destiny.Z);
        float howMuchToMultiply = 1;

        // Iterate in the 20 Joints
        foreach (JointType item in Enum.GetValues(typeof(JointType)))
        {
            newJoint = skToBeMoved.Joints[item];

            // This adjust, try to keeps the skToBeMoved in the desired position
            if (newJoint.Position.X < 0)
                howMuchToMultiply = 1; // if the point is in a negative position, carry it to a "more positive" position
            else
                howMuchToMultiply = -1; // if the point is in a positive position, carry it to a "more negative" position

            // applying the new values to the joint
            SkeletonPoint pos = new SkeletonPoint()
            {
                X = newJoint.Position.X + (howMuchMoveToX * howMuchToMultiply),
                Y = newJoint.Position.Y, // * (float)whatToMultiplyY,
                Z = newJoint.Position.Z, // * (float)whatToMultiplyZ
            };

            newJoint.Position = pos;
            skToBeMoved.Joints[item] = newJoint;

            //if (skToBeMoved.Joints[JointType.HipCenter].Position.X < 0)
            //{
            //    if (item == JointType.HandLeft)
            //    {
            //        if (skToBeMoved.Joints[item].Position.X > 0)
            //        {

            //        }
            //    }
            //}
        }

        return skToBeMoved;
    }

Actualy, only X position is considered.

Now, THE PROBLEM:

If i stand in a negative position, and move my hand to a positive position, a have a strange behavior, look this image

enter image description here

To reproduce this behaviour you could use this code

using (SkeletonFrame frame = e.OpenSkeletonFrame())
        {
            if (frame == null)
                return new Skeleton();

            if (skeletons == null || skeletons.Length != frame.SkeletonArrayLength)
            {
                skeletons = new Skeleton[frame.SkeletonArrayLength];
            }
            frame.CopySkeletonDataTo(skeletons);

            Skeleton skeletonToTest = skeletons.Where(s => s.TrackingState == SkeletonTrackingState.Tracked).FirstOrDefault();

            Vector4 newPosition = new Vector4();
            newPosition.X = -0.03412333f;
            newPosition.Y = 0.0407479f;
            newPosition.Z = 1.927342f;
            newPosition.W = 0; // ignored

            skeletonToTest.MoveTo(newPosition);
        }

I know, this is simple math, but i cant figure it out why this is happen. Any help will be apreciated.

Rondarondeau answered 25/11, 2012 at 15:44 Comment(4)
it should be a matter of adding the new position translation vector to each joint position in the skeleton and nothing moreDelija
@George Profenza Yes, it is! Whats your code modifications to solve it?Rondarondeau
Glad you sorted out, I was out when you replied. Still, from my point of view, if Vector4 destiny is a relative position to translate towards it's just a matter doing doing someting like currentPositionVector += translationVector(in pseudo, as in, currentJoint.x += newPos.x,same for y and z). If destiny is absolute, you would use the difference between the current position and the new position. The part that puzzles me in your approach is why you flip (multiply by -1) the difference vector. Also, when you get the difference vector, you seem to only add the to the X component...Delija
...I haven't used the Kinect SDK much, are the skeleton positions 3D positions in relation to the kinect or converted 2D screen coordinates ?Y = newJoint.Position.Y + (0) and same for Z wouldn't change those coordinates.Delija
R
9

Problem solved. This is the code

public static Skeleton MoveTo(this Skeleton skToBeMoved, Vector4 destiny)
    {
        Joint newJoint = new Joint();

        ///Based on the HipCenter (i dont know if it is reliable, seems it is.)
        float howMuchMoveToX = (skToBeMoved.Joints[JointType.HipCenter].Position.X - destiny.X) * -1;
        float howMuchMoveToY = (skToBeMoved.Joints[JointType.HipCenter].Position.Y - destiny.Y) * -1;
        float howMuchMoveToZ = (skToBeMoved.Joints[JointType.HipCenter].Position.Z - destiny.Z) * -1;

        // Iterate in the 20 Joints
        foreach (JointType item in Enum.GetValues(typeof(JointType)))
        {
            newJoint = skToBeMoved.Joints[item];

            // applying the new values to the joint
            SkeletonPoint pos = new SkeletonPoint()
            {
                X = (float)(newJoint.Position.X + (howMuchMoveToX)),
                Y = (float)(newJoint.Position.Y + (howMuchMoveToY)),
                Z = (float)(newJoint.Position.Z + (howMuchMoveToZ))
            };

            newJoint.Position = pos;
            skToBeMoved.Joints[item] = newJoint;
        }

        return skToBeMoved;
    }
Rondarondeau answered 25/11, 2012 at 23:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.