Developer Guide
This is a terse guide to the classes and methods of the Leap javascript API.
The Leap object is a singleton
library, like jQuery's $ object. It is your bridge to the stream of data recieved from
the Leap detector.
Do not taunt Happy Fun Ball!
The only class you should manually instantiate is the Controller. (and for most applications you'll only want one
controller instance.)
None of the other classes should be manually created by you -- they should be retrieved by methods of the
controller -- or methods of objects
retrieved by controller methods ... and so on.
Getting Frame Data from your Leap Motion detector
In order to get information from your Leap Motion detector you need
- a Leap Motion Detector plugged into your computer
- the Leap Motion software installed.
Once this is established, you need to interact with the data coming from the hardware. This site covers
interactions based on the javascript API library that binds Leap Motion data
to a javascript code that listens for this data to stream to it.
There are three ways to access this data:
- Call Leap.loop, as shown in this jsfiddl.e
- Create a controller and passively listen for
frame events.
- Create a controller and actively call
controller.frame() when you want motion data.
Event listening from the static Leap class
Leap.loop(handler) allows you to skip creating a controller instance.
Leap.loop(function(frameInstance){
...
});
Event listening from a Controller
if you listen to a controllers' events each and every frame will be broadcast from the Leap detector to your
handler.
var my_controller = new Leap.Controller({enableGestures: true});
// see Controller documentaion for option details
my_controller.on('frame', function(frame_instance){ ... });
my_controller.connect();
Polling will allow you to get one (or more) frames from the controller's stack, whenever and as often or rarely as
you wish.
var my_controller = new Leap.Controller({enableGestures: true});
my_controller.on('connect', function(){
setInterval(function(){
var frame = my_controller.frame();
}, 500);
});
my_controller.connect();
This has several potential
advantages:
- You can control the number of measurements yourself; you might only need 10 frames of information per second, so
why do six times as much processing?
tying your polling to your rendering is more efficient since there may be no value to getting more than one frame
per render cycle.
- You can get the best sample out of several measurements. You can sample the last 8 frames, and get the one with
the most
pointers/fingers/hands and use that to drive your application.
- You can choose whether or not to take signal data. After the user pushes a virtual button, you can stop
listening
while you resolve an action,
then pick up listening later on.
Units of Measurement
All distances are expressed in millimeters, as a float. If you want to get relative (percent) measurements,
use the InteractionBox.normalizePoint method.
See the Leap.InteractionBox documentation for axis orientation.
All angles are measured in Radians.
To convert to degrees, multiply by 180/Math.PI.
All time/timestamp measurements are given in milliseconds; 1000 milliseconds = 1 second. Timestamps are
relative measures of time since the Leap Motion controller started.
Frame indexes reflect the LIFO nature of the Leap.Controller's frames
collection.
-
my_controller.frames(0) == my_controller.frames() == the most recent frame.
-
my_controller.frames(1) is the previous frame
-
my_controller.frames(1) is two frames ago
and so on. Keep in mind that frames are constantly being pushed onto the stack, so my_controller(2)
will
be a different frame in a few milliseconds.
When in doubt use frame.id to identify/compare frames.
All coordinates/positions are returned as an array of three distances (see above). See
Leap.InteractionBox
for methods on normalizing/denormalizing coordinates.
scaleFactor
Leap.Hands and Leap.Frames have scaleFactor functions.
Scale factor indicates a change in distance between things over time. For hands, this means the change in distance
between the fingers.
the function has a parameter -- a baseline frame.
Scale factor for hands
Hands' scale factor reflects the relative "Jazz handiness" of your fingers, compared with the baseline spread
in
thei passed in frame.
-
If you pinch all your fingers together since the reference frame, your hand's scaleFactor will be < 1.
-
If you expand ("jazz hands") your fingers farther apart, your hands' scaleFactor will be > 1.
Scale factor for frames
When frame.scaleFactor(old_frame) is called, it reflects the relative distance between the hands
--
the "fish measuring factor".
- if you move your hands apart, the scale factor will be > 1
- if you move your hands together, the scale factor will be < 1
If Leap cannot relate the baseline reference with the current frame/hand data, the scaleFactor will be 1.
Valid and Invalid function return results
Any function which returns an instance object (Pointable, Frame, Hand,...) will ALWAYS return an object,
even under conditions where returning an object is impossible. (bad parameters, your hands aren't in front of the
detector, etc.)
Instead of returning false, null, or throwing an error, an invalid instance will be returned.
This means you will want to examine the valid property of all returned objects. Its a boolean property
and all Leap instances have one.
Leap Methods
Leap.Loop(callback)
This static method of the Leap global object fires repeatedly, approximately sixty times a second.
See Getting Frame Data from your Leap Motion detector for other ways of accomplishing
data monitoring..
The Callback receives a single Leap.Frame instance.
Leap Classes
Leap.Frame
A collection of state information fed back from the Leap Motion hardware. A frame is the "root" data unit;
it contains all the positional data that streams from the Leap Motion detector,
Fingers/Tools/Pointables at a given instant in time.
See Getting Frame Data from your Leap Motion controller for documentation on getting
frames.
A note on Frame.Fingers, Frame.pointables, and Frame.tools:
frame.fingers, frame.tools and frame.pointables are different collections of
instances which are all instances of
the Leap.Pointables base class. (there is no special Leap.Tools or Leap.Fingers classs
--
just Leap.Pointable.)
- The pointables collections contains all the pointables also found in tools and fingers.
- The tools collections and the fingers collections are exclusive; there is no pointer which can be
found
in both the fingers collection and the tools collection
- All pointables in these root collections can be found in the frame.hands properties..
- Any of these collections can be empty, if the user's hands/fingers/tools aren't picked up by the Leap
Motion
detector.
- All fingers/tools/pointables from both hands are stored with no ordering in these root level collections.
Properties
- id
- string A unique id of this Frame instance
- pointables
- [Leap.Pointable] array of all fingers and tools from both hands.
- fingers
- [Leap.Pointable] array of all fingers from both hands.
- tools
- [Leap.Pointable] array of all tools from both hands.
- gestures
- [Leap.Gesture] array of zero or more detected gestures.
Requires configuration of the Leap.Controller to be present (see
enableGestures.)
- hands
- [Leap.Hand] array of 0..2 Leap.Hands.
- timestamp
- int microseconds since the Leap detector started
- valid
- boolean
indicates whether the frame is valid. An invalid frame contains no tracking data
but does conform to the frame API.
- Invalid
- Leap.Frame an invalid instance of a frame.
Methods
- dump
- (): string returns a JSON-formatted string (not object) containing
all the data of the frame.
- finger
- (id: string *): Leap.Pointable
returns a finger from the fingers collection(see above).
- pointable
- (id: string *): Leap.Pointable
returns a pointable from the pointables collection (see above).
- hand
- (id: string): Leap.Hand
returns a hand from the hands collection (see above).
- translation
- (sinceFrame: int): [int/mm]
The movement, in millimeters, of both hands since the passed-in timestamp,
- scaleFactor
- (sinceFrame: int): float
The scale factor between both hands since the passed-in timestamp.
- rotationAngle
- (sinceFrame: int, axis: int): float (radians -- 0..π)
The angle of rotation around the rotation axis (0, 1, or 2) of both hands since the passed-in timestamp
The returned angle is expressed in radians measured clockwise around the rotation axis (using the right-hand
rule).
- rotationAxis
- (sinceFrame: int): [int]
the information described in rotationAngle, for all three axes,
of both hands since the passed-in timestamp
- rotationMatrix
- (sinceFrame: integer): [int]
The transform matrix expressing the rotation derived from the overall rotational motion,
of both hands since the passed-in timestamp,
The Leap derives frame rotation from the relative change in position and orientation
of all objects detected in the field of view.
* Warning: IDs can change between frames -- there is no guarantee that an ID from a
previous frame will work as a parameter for subsequent calls to frame.finger(). the IDs are
only functional within the lifespan of a single frame.
Leap.Pointable
The Pointable class represents detected finger or tool **.
Both fingers and tools are classified as Pointable objects.
Use the Pointable.tool property to determine whether a Pointable object represents a tool or finger
Note that Pointable objects can be invalid, which means that they do not contain valid tracking data and do not
correspond to a physical entity.
Invalid Pointable objects can be the result of asking for a Pointable object using an ID from an earlier frame when
no Pointable objects with that ID exist in the current frame.
Properties
- id
- string
- Invalid
- Pointable an invalid instance of a Pointable.
- length
- number (mm)
- tipVelocity
- [number]
the rate of change of the tip's position in mm/second.
- tipPosition
- [number/mm]
the distance from the Leap Detector to the tip of the finger (raw data).
- stabilizedTipPosition
- [number/mm]
the distance from the Leap Detector to the tip of the finger, stabilized
- direction
- [number] (three numbers) the direction the pointer is pointing.
- width
- number (mm)
the est. diameter of the tool. Finger fatness.
- tool
- boolean whether the finger is classified as a finger or a tool.
(see Leap.Frame).
- valid
- boolean
** The Leap classifies a detected entity as a tool when it is thinner, straighter, and longer than a
typical finger.
Leap.Controller
Represents the connection to a single Leap detector. You can have multiple controllers in a single run time.
Note that Leap.Controller is a Javascript class;
whereas the Leap Motion controller refers to an actual piece of hardware -- the box.
the below code creates a Leap.Controller, listening to localhost.
var controller = new Leap.Controller({
host: '127.0.0.1',
port: 6437,
enableGestures: true,
frameEventName: 'animationFrame'
});
Any or all these properties are optional; you can also create a controller with a simpler parameter set:
var controller = new Leap.Controller({enableGestures: true});
Properties
- connection
- Leap.Connection the object maintaining communication between the Leap
detector and the Controller instance.
Methods
- connect
- () initializes communication/events between the Leap Detector and the controller. (if it's plugged
in...)
- frame
- (index: int?) Leap.Frame
Index is a number from 0 to the number of frames retained in the "frame stack"
(currently up to 60 frames are retained; however when the controller starts, the stack may have fewer than 60
frames.
The most recent frame's index is 0 (zero); the frame before that has index 1, and so on.
my_controller.frame() will return the most recent frame.***
- on
- (event: string, handler: function)
binds a listener function to an event.
*** this method ALWAYS returns a frame, even if there is no frame at the stack matching the
index
you pass in. If you pass in an index for which there is no frame, an invalid frame will be returned.
Controller Events
- connect
- The client is connected to the websocket server
- frame
- A frame is finishing being processed by the controller.
This event is either driven by the
animationFrame or the deviceFrame event,
depending which is the Leap.Controller was created with.
The frame is passed as an argument to the event handler
- ready
- The protocol has been selected
- disconnect
- The client disconnects from the websocket server
- focus
- The browser received focus
- blur
- The browser loses focus
- deviceConnected
- A Leap device has been connected
- deviceDisconnected
- A Leap device has been disconnected
- animationFrame
- A frame being emitted in time with the animation loop. The frame is passed as an
argument to the event handler
- deviceFrame
- A frame being emitted by the connection to the Leap device. The frame is passed as an
argument to the event handler
- protocol
- The protocol has been selected for the connection. The protocol object is passed as an
argument to the event handler
Here is a typical initialization cycle for interacting with a Leap Motion controller:
var controller = new Leap.Controller();
controller.on('connect', function() {
console.log("Successfully connected.");
});
controller.on('deviceConnected', function() {
console.log("A Leap device has been connected.");
});
controller.on('deviceDisconnected', function() {
console.log("A Leap device has been disconnected.");
});
controller.connect();
Leap.Connection
@TODO: document
Leap.Hand
The Hand class reports the physical characteristics of a detected hand.
Hands are accessed as properties of the Leap.Frame's hand array; at this point, up to two
hands can be simultaneously tracked and returned with frame data.
Hand tracking data includes a palm position and velocity;
vectors for the palm normal and direction to the fingers;
properties of a sphere fit to the hand; and lists of the attached fingers and tools.
See the Leap.Frame class documentation for the difference between Pointables, Fingers and
Tools.
The below illustration shows the hands' palmNormal
Properties
- id
- string
Note that hand IDs unlike many other IDs in the system, are relatively consistent from frame to frame, at
least
in the short term. When comparing two
frame.hands arrays, there is no guarantee that the
hands will be in the same order, but if both frames have two hands,
you can likely match up hands by comparing their ids.
- Invalid
- Hand an invalid instance of a Hand.
- direction
- [number] (three numbers) the direction the hand is pointing;
roughly speaking, a vector from the palm to the midpoint of the fingers.
- palmNormal
- [number] (three numbers)
the direction the palm is pointing.
- palmPosition
- [float/mm]
the location of the center of the palm, in millimeters.
- stabilizedPalmPosition
- [number] (three numbers)
the location of the center of the palm, in millimeters -- stabilized
- palmVelocity
- [number] (three numbers -- mm/second)
The rate of change of the palm position in millimeters/second.
- sphereCenter
- [number] (three numbers)
the center of a "virtual sphere" that the hand is holding; see the illustration below.
"cupping your fingers" makes the ball smaller, and therefore, brings the sphereCenter closer to your palm.
- fingers
- [Leap.Pointable]
an array of the hands' Pointables which have been classified as fingers.
- tools
- [Leap.Pointable]
an array of the hands' Pointables which have been classified as tools.
- pointables
- [Leap.Pointable]
an array of all of the hands' Pointables.
- valid
- boolean
whether or not the hand is valid.
Methods
- finger
- (id: string *): Leap.Pointable
returns a finger from the fingers collection(see above).
- pitch
- number (-π...π) radians
Rotation around the x-axis;
or, the angle between the negative z-axis and the projection of the vector onto the y-z plane.
If the vector points upward, the returned angle is between 0 and pi radians (180 degrees).
If it points downward, the angle is between 0 and -pi radians.
- roll
- number (-π...π) radians
rotation around the z-axis;
or, the angle between the y-axis and the projection of the vector onto the x-y plane.
If the vector points to the left of the y-axis, then the returned angle is between 0 and pi radians (180
degrees).
If it points to the right, the angle is between 0 and -pi radians.
- yaw
- number (-π...π) radians
rotation around the z-axis;
or, the angle between the y-axis and the projection of the vector onto the x-y plane.
If the vector points to the left of the y-axis, then the returned angle is between 0 and pi radians (180
degrees);
if it points to the right, the angle is between 0 and -pi radians.
- rotationAxis
- (sinceFrame: Leap.Frame): [number]
The transform matrix expressing the rotation derived from the change in orientation of this hand,
and any associated fingers and tools, between the current frame and the specified frame.
If a corresponding Hand object is not found in sinceFrame,
or if either this frame or sinceFrame are invalid Frame objects, then this method returns an identity matrix.
- rotationAxis
- (sinceFrame: Leap.Frame): [number]
The axis of rotation derived from the change in orientation of this hand, and any associated fingers and
tools,
between the current frame and the specified frame.
The returned direction vector is normalized.
If a corresponding Hand object is not found in sinceFrame,
or if either this frame or sinceFrame are invalid Frame objects, then this method returns a zero vector.
- rotationAngle
- (sinceFrame: Leap.Frame, axis: [number]?): [number]
returns the rotation relative to a reference Frame.
If a second parameter is passed in, the angle is the reference angle to measure around.
- scaleFactor
- (sinceFrame: Leap.Frame): number: 0..?
This is a "Pinchiness factor". scaleFactor for hands the change in the
relative extent of all fingers of the hand between the reference frame and this frames.
- translation
- (sinceFrame: Leap.Frame): [float/mm]
The relative position(movement) of the hand (palm) since the given frame, in millimeters
If Leap cannot relate this hand with a hand in the passed-in frame, the scaleFactor will be 1.
Leap.InteractionBox
A representation of the "airspace" in which the Leap Motion controller can measure/see your hands and fingers.
Note that the range of the interaction box may change with hardware or software advances.
Use the interaction boxes' properties to scale your measurements -- don't hard code these values in your javascript.
the Axes' orientation
- The x-axis goes to the right. 0 on the x axis is the middle of the Leap Motion controller.
- The y-axis goes up, from the Leap Motion controller; you will likely have to negate it
to make it consistent with screen/DOM graphic coordinates. 0 on the y axis is very close to the Leap Motion
detector.
- The z-axis points towards you. 0 on the z axis is right above the detector. Your monitor will be at -Z, your
head will have a +Z measurement.
Properties
- center
- [float/mm]
The center of the interaction box, in millimeters
- depth
- [float/mm]
the z-size of the detection area.
- height
- [float/mm]
the y-size of the detection area.
- width
- [float/mm]
the x-size of the detection area.
- valid
- boolean
whether the InteractionBox is valid
- Invalid
- InteractionBox
an invalid InteractionBox instance.
Methods
- normalizePosition
- ([number/mm): [number/-1..1]
Scales the imput vector by the height/width/depth of the InteractionBox, returning a vector
with values in the -1...1 range.
- denormalizePosition
-
([number/-1...1]): [number/mm]
takes a "normalized" vector array and returns a vector array in the units of the interaction box; the reverse
of normalizePosition.
Gesture
The Gesture class represents a recognized movement by the user.
The Leap watches the activity within its field of view for certain movement patterns typical of a user gesture or
command. For example, a movement from side to side with the hand can indicate a swipe gesture, while a finger poking
forward can indicate a screen tap gesture.
When the Leap recognizes a gesture, it assigns an ID and adds a Gesture object to the frame gesture list. For
continuous gestures, which occur over many frames, the Leap updates the gesture by adding a Gesture object having
the same ID and updated properties in each subsequent frame.
Important: Recognition for each type of gesture must be enabled; otherwise no gestures are recognized or reported.
Subclasses of Gesture define the properties for the specific movement patterns recognized by the Leap.
The Gesture subclasses for include:
- CircleGesture
- A circular movement by a finger
- SwipeGesture
- A straight line movement by the hand with fingers extended.
- ScreenTapGesture
- A forward tapping movement by a finger.
- KeyTapGesture
- A downward tapping movement by a finger.
Number of gestures produced
Circle and swipe gestures are continuous and these objects can have a state of start, update, and stop.
The screen tap gesture is a discrete gesture. The Leap only creates a single ScreenTapGesture object appears for
each tap and it always has a stop state.
Getting Gesture instances from a Frame object.
You can get a list of gestures from the Frame gestures array.
You can also use the Frame gesture() method to find a gesture in the current frame using an ID value obtained in a
previous frame.
Gesture objects can be invalid.
Properties
- id
-
number All gestures belonging to the same continuous gesture will have the same ID.
Can be passed into
my_frame.gesture(my_gesture.id) to get updated versions of a gesture.
- duration
- int the duration (in microseconds) of the gesture, as of the frame
from which the gesture was retrieved.
- pointableIds
- [string] the ids of fingers associated with this gesture (if any)
- handIds
- [string] the ids of hands associated with this gesture (if any)
- state
- string/'start', 'update' or 'stop'
where in the "clown car o' gesture" stream the current gesture is
-- the first, the last, or somewhere in the middle.
Tap gestures will always have a 'stop' state.
- type
-
string/circle, 'swipe', 'screenTap', or 'keyTap'