Book Image

Leap Motion Development Essentials

By : Mischa Spiegelmock
Book Image

Leap Motion Development Essentials

By: Mischa Spiegelmock

Overview of this book

Leap Motion is a company developing advanced motion sensing technology for human–computer interaction. Originally inspired by the level of difficulty of using a mouse and keyboard for 3D modeling, Leap Motion believe that moulding virtual clay should be as easy as moulding clay in your hands. Leap Motion now focus on bringing this motion sensing technology closer to the real world. Leap Motion Development Essentials explains the concepts and practical applications of gesture input for developers who want to take full advantage of Leap Motion technology. This guide explores the capabilities available to developers and gives you a clear overview of topics related to gesture input along with usable code samples. Leap Motion Development Essentials shows you everything you need to know about the Leap Motion SDK, from creating a working program with gesture input to more sophisticated applications covering a range of relevant topics. Sample code is provided and explained along with details of the most important and central API concepts. This book teaches you the essential information you need to design a gesture-enabled interface for your application, from specific gesture detection to best practices for this new input. You will be given guidance on practical considerations along with copious runnable demonstrations of API usage which are explained in step-by-step, reusable recipes.
Table of Contents (12 chapters)

Quick start


Congratulations on your purchase of a genuine fine quality Leap Motion gesture input device! This handy guide will walk you through the assembly, proper usage, and care of your Leap Motion.

To get started, remove your Leap Motion SDK and Leap Motion™ device from the box and unpack the shared object files and headers from their shrink-wrap. Gently place your SDK in a handy directory and fire up your favorite IDE to begin.

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

We'll get things going right away with a short C++ application to illustrate how to interact with the Leap SDK to receive events and input.

#include <iostream>
#include <Leap.h>

class Quickstart : public Leap::Listener {
public:
    virtual void onConnect(const Leap::Controller &);
    virtual void onFrame(const Leap::Controller &);
};

To interact with the Leap software, we will begin by creating a subclass of Leap::Listener and defining the callback methods we wish to receive. While it is possible to poll the controller for the current frame, generally you will want to make your program as responsive as possible which is most easily accomplished by acting on input events immediately via callbacks. In case you're wondering, the primary available callback methods are:

  • onInit: This indicates that the listener is added to a controller and called only once.

  • onExit: This indicates that the controller is destroyed or the listener is removed.

  • onConnect: This indicates that the device is connected and recognized by the driver and is ready to start processing frames.

  • onDisconnect: This indicates that the device is disconnected. Connection state can also be polled by checking controller.isConnected() so that you don't need to keep track of whether the controller is plugged in or not. (An earlier version of the SDK lacked this state accessor but the kind folks at Leap Motion realized us devs are really lazy).

  • onFrame: This indicates that a new frame of input data has been captured and processed. This is the only handler you really need to implement if you want to make use of the Leap.

Let's implement our onConnect handler real quick so that we can verify that the controller driver and SDK are communicating with the device properly. If everything is working as it should be, the following code should cause a message to be emitted on stdout when the device is plugged in to a USB port:

void Quickstart::onConnect(const Leap::Controller &controller) {
    std::cout << "Hello, Leap user!\n";
}

We can display a friendly contrived greeting to ourselves when the program is run with the controller connected and the driver software is running. This will cause breathless anticipation in your users as they prepare themselves to experience the magic and wonder of this fantastic new input technology.

A listener is attached to a Leap::Controller, which acts as the primary interface between the Leap driver and your application. A controller tracks processed frames, device connection state, configuration parameters, and invokes callback methods on a listener.

To begin receiving events, instantiate a new listener and a controller:

int main() {
    // create instance of our Listener subclass
    Quickstart listener;
    
    // create generic Controller to interface with the Leap device
    Leap::Controller controller;
    
    // tell the Controller to start sending events to our Listener
    controller.addListener(listener);
  …

If you place your hands over the device Quickstart::onFrame() will start being called. Let's create an onFrame handler that reports on the horizontal velocity of the first finger or tool detected:

void Quickstart::onFrame(const Leap::Controller &controller) {
    const Leap::Frame frame = controller.frame();

controller.frame() returns a Frame instance, which contains information detected about our scene at a specific point in time. It has a single optional parameter history, which allows you to travel backwards through the misty sands of time to compare frames and determine hand changes over time. Unfortunately this time machine is rather limited; only about 60 previous frames are stored in the controller.

    // do nothing unless hands are detected
    if (frame.hands().empty()) return;

Get used to making these sorts of checks. You'll be seeing a lot more of them. Here, we have no interest in processing this frame unless there are hands in it.

    // first detected hand
    const Leap::Hand firstHand = frame.hands()[0];
    // first pointable object (finger or tool)
    const Leap::PointableList pointables = firstHand.pointables();
    if (pointables.empty()) return;
    const Leap::Pointable firstPointable = pointables[0];

All fingers attached to a hand and all tools that the hand is grasping are returned as a PointableList, which behaves like an std::vector, including providing an iterator for people who are into that. Most commonly we will want to find out where a pointable is in space and how fast it is moving, which we can easily find out with tipPosition() and tipVelocity() respectively. Both return Leap::Vectors consisting of X, Y, and Z components.

    std::cout << "Pointable X velocity: " << firstPointable.tipVelocity()[0] << endl;

If you wave an outstretched finger or a tool (a chopstick works pretty well if you happen to have one lying around) back and forth over the controller you will be rewarded with the following riveting output:

Pointable X velocity: -223.937
Pointable X velocity: -117.421
Pointable X velocity: -242.293
Pointable X velocity: -141.43
Pointable X velocity: -61.9314
Pointable X velocity: 9.85328
Pointable X velocity: 41.9575
Pointable X velocity: 71.7436
Pointable X velocity: 96.0459
Pointable X velocity: 116.465

Leftwards motion is represented by negative values (mm/s). Rightwards motion is positive.

Tip

A note on the sample code

Because of frequent changes to the SDK, your best bet for finding the most up-to-date code samples is to check out the GitHub repository.

All sample code can be found at https://github.com/openleap/leapbook. This program and others like it can be built using the following command on Mac OS X or Linux using GCC or clang:

$ g++ quickstart.cpp -lLeap –Lpath/to/Leap_SDK/lib/libc++ –Ipath/to/Leap_SDK/include –o quickstart

Note that path/to/Leap_SDK should be replaced with the location of your Leap_SDK directory. It may be helpful to set an environment variable with the path or install the libraries and headers system-wide.