Search code examples
javaleap-motion

missed tap gestures from leap motion in java


I wrote a test code to see if my tap gestures are accepted from leap motion. After running the code I noticed that I have to tap really aggressively and even then, I only get a tap received once in every few taps. How can I change my code to prevent this ?

(Please notice, I am very new to coding so plz be elaborate, thanks)

FILE #1

    package com.leaptoarduino;
    import com.leapmotion.leap.Controller;
    import com.leapmotion.leap.Gesture;
    public class Leapd
    {
        //Main
        public static final void main(String args[])
        {
            //Initialize serial communications
            RS232Protocol serial = new RS232Protocol();
            serial.connect("COM3");
            //Initialize the Leapd listener
            LeapdListener leap = new LeapdListener(serial);
            Controller controller = new Controller();
            controller.addListener(leap);
            controller.enableGesture(Gesture.Type.TYPE_KEY_TAP);
            //Set up controller for gestures
            controller.config().setFloat("Gesture.KeyTap.MinDownVelocity", 5.0f);
            controller.config().setFloat("Gesture.KeyTap.HistorySeconds", .8f);
            controller.config().setFloat("Gesture.KeyTap.MinDistance", 20.0f);
            controller.config().save();     
        }

     }

FILE #2

    package com.leaptoarduino;
    import com.leapmotion.leap.*;
    import com.leapmotion.leap.Gesture.Type;
    import com.leapmotion.leap.KeyTapGesture;
    public class LeapdListener extends Listener
    {
    //Serial port that will be used to communicate with the Arduino
    private RS232Protocol serial;
    //Constructor
    public LeapdListener(RS232Protocol serial)
    {
        this.serial = serial;
    } 
    //Member function: onInit
    public void onInit(Controller controller)
    {
        System.out.println("Initialized");
    }
    //Member function: onConncect
    public void onConnect(Controller controller)
    {
       System.out.println("Connected");
    } 
    //Member Function: onDisconnect
    public void onDisconnect(Controller controller)
    {
       System.out.println("Disconnected");
    } 
    //Member Function: onExit
    public void onExit(Controller controller)
    {
       System.out.println("Exited");
    } 
    //Member Function: onFrame
    public void onFrame(Controller controller)
    {

        //Get the most recent frame
        Frame frame = controller.frame();
        //Verify a hand is in view
        if (frame.hands().count() > 0)
        {
            GestureList gestures = frame.gestures();
            for (Gesture gesture: gestures)
            {
                if (gesture.type() == Type.TYPE_KEY_TAP)
                {
                    KeyTapGesture keytap = new KeyTapGesture (gesture);
                    System.out.println("KEYTAPPED");
                }
            }

            //Send the tap data to the Arduino
            // TBD
            //Give the Arduino some time to process our data
            try { Thread.sleep(30); }
            catch (InterruptedException e) { e.printStackTrace(); }
        }
    }
}

Solution

  • When you sleep the thread in the OnFrame handler, you are going to miss frames from the Leap Motion service. Part of your problem is probably that the tap gestures are recognized in those missed frames. Frame.gestures() takes a "sinceFrame" parameter to avoid this problem: frame.gestures(sinceFrame) gives you all the gestures that occurred between sinceFrame and the current frame and thus you don't miss any when frames are dropped or skipped. What you do is save the current frame to a lastFrameProcessed variable every time your onFrame handler runs. You pass this lastFrameProcessed variable to gestures() to get the complete gesture list. Something like:

    Frame lastFrameProcessed = Frame.invalid();
    public void onFrame(Controller controller)
    {
    
        //Get the most recent frame
        Frame frame = controller.frame();
        //Verify a hand is in view
        if (frame.hands().count() > 0)
        {
            GestureList gestures = frame.gestures(lastFrameProcessed);
            for (Gesture gesture: gestures)
            {
                if (gesture.type() == Type.TYPE_KEY_TAP)
                {
                    KeyTapGesture keytap = new KeyTapGesture (gesture);
                    System.out.println("KEYTAPPED");
                }
            }
    
            //Send the tap data to the Arduino
            // TBD
            //Give the Arduino some time to process our data
            try { Thread.sleep(30); }
            catch (InterruptedException e) { e.printStackTrace(); }
        }
        lastFrameProcessed = frame;
    }