Hands are the main entity tracked by the Leap Motion controller. The controller maintains an inner model of the human hand and validates the data from its sensors against this model. This allows the controller to track finger positions even when a finger is not completely visible. Note that it is possible for movement or changes in position to be lost when a finger is behind or directly in front of the hand (from the point of view of the controller). The Leap Motion software matches the internal model against the existing data. In some cases, the software can make an incorrect match – for example, identifying a right hand as a left hand.
The Hand class represents a physical hand detected by the Leap. A Hand object provides access to lists of its pointables as well as attributes describing the hand position, orientation, and movement.
Hands can be identified by left versus right handedness. In addition, each hand is assigned an ID value when the hand is first detected. If you remove a hand from the Leap Motion field of view and then re-insert it, a new ID is assigned (use the timeVisible attribute to tell whether a hand is newly detected or not). New hand IDs are also assigned if the Leap Motion software decides it has misclassified a hand and must change its type from right to left or vice versa.
Get Hand objects from a Frame:
Frame frame = controller.Frame (); // controller is a Controller object
HandList hands = frame.Hands;
Hand firstHand = hands [0];
Or, if you know the ID from a previous frame:
Hand knownHand = frame.Hand (handID);
You can also get hands by their relative positions in the frame:
Frame frame = controller.Frame (); // controller is a Controller object
HandList hands = frame.Hands;
Hand leftmost = hands.Leftmost;
Hand rightmost = hands.Rightmost;
Hand frontmost = hands.Frontmost;
Note that the the leftmost() and rightmost() functions only identify which hand is farthest to the left or right. Use the Hand isLeft or isRight attribute to tell if a hand object represents a left or a right hand.
A hand is described by its handedness, position, orientation, posture, and motion:
The hand’s position is given by its palm position attribute, which provides a vector containing the 3-dimensional coordinates of the palm center point in millimeters from the Leap Motion origin. The hand’s orientation is given by two vectors: the direction, which points from the palm center towards the fingers, and the palm normal, which points out of the palm, perpendicular to the plane of the hand.
The movement of the hand is given by the velocity attribute, which is a vector providing the instantaneous motion of the hand in mm/s. You can also get motion factors that translate how a hand has moved between two given frames into translation, rotation, and scaling values.
The following code snippet illustrates how to get a Hand object from a frame and access its basic attributes:
Hand hand = frame.Hands.Rightmost;
Vector position = hand.PalmPosition;
Vector velocity = hand.PalmVelocity;
Vector direction = hand.Direction;
You can get the fingers associated with a hand as a list or individually using an ID obtained in a previous frame.
By list:
// hand is a Hand object
PointableList pointables = hand.Pointables;
FingerList fingers = hand.Fingers;
By ID from a previous frame:
Pointable knownPointable = hand.Pointable (pointableID);
To get a finger by relative position within the Leap field of view, use the right-, left- and frontmost functions of the matching list class:
// hand is a Hand object
Pointable leftPointable = hand.Pointables.Leftmost;
Finger rightFinger = hand.Fingers.Rightmost;
Finger frontFinger = hand.Fingers.Frontmost;
Note that these functions are relative to the Leap Motion origin, not to the hand itself. To get the fingers relative to the hand, you can use the Leap Matrix class to transform the finger positions into the hands frame of reference.
You can compute the hand orientation angles using the Hand direction and normal vectors.
The normal vector points perpendicularly out of the hand; the direction vector points forward.
The Vector class defines functions for getting the pitch (angle around the x-axis), yaw (angle around the y-axis), and roll (angle around the z-axis):
float pitch = hand.Direction.Pitch;
float yaw = hand.Direction.Yaw;
float roll = hand.PalmNormal.Roll;
Note that the roll function only provides the expected angle when used with a normal vector.
Sometimes it is useful to obtain the coordinates of the fingers of a hand with respect to the hand’s frame of reference. This lets you sort the fingers spatially and can simplify analysis of finger positions. You can create a transform matrix using the Leap Matrix class to transform the finger position and direction coordinates. The hand frame of reference can be usefully defined by the hand’s Basis and PalmPosition. The Basis orients the x-axis sideways across the hand, the z-axis pointing forward, and the y-axis parallel with the palm normal. The origin of the transform is the PalmPosition.
Frame frame = controller.Frame ();
for (int h = 0; h < frame.Hands.Count; h++) {
Hand leapHand = frame.Hands [h];
Vector handXBasis = leapHand.PalmNormal.Cross (leapHand.Direction).Normalized;
Vector handYBasis = -leapHand.PalmNormal;
Vector handZBasis = -leapHand.Direction;
Vector handOrigin = leapHand.PalmPosition;
Matrix handTransform = new Matrix (handXBasis, handYBasis, handZBasis, handOrigin);
handTransform = handTransform.RigidInverse ();
for (int f = 0; f < leapHand.Fingers.Count; f++) {
Finger leapFinger = leapHand.Fingers [f];
Vector transformedPosition = handTransform.TransformPoint (leapFinger.TipPosition);
Vector transformedDirection = handTransform.TransformDirection (leapFinger.Direction);
// Do something with the transformed fingers
}
}
The HandList class acts like a vector-style array and supports iterators. You cannot remove or alter the member objects of a hand lists received from the Leap Motion API, but you can combine lists of the same object type.
To use an iterator with a list class:
foreach (Hand hand in handList) {
Console.WriteLine (hand.ToString ());
}
The HandList class defines additional functions for getting a member of the list based on its relative position within the Leap coordinate system. These functions include leftmost(), rightmost(), and frontmost(). The following snippet illustrates how to get the hand object furthest to the right:
Hand furthestRight = frame.Hands.Rightmost;