Hi all,
I have been toying around with the Leap Motion controller and it’s API in Python.
My goal is to write some scripts in Rhino Python which leverage the data acquired from the Leap controller. I thought I’d share my findings so that others may benefit but also to ask questions relating to the stability of running Leap within Rhino Python.
The setup process to access the Leap libraries from within Rhino Python is as follows:
Created a rhino python script called leapTst.py in a folder
To the folder I added the relevant files from the Leap SDK Dev Kit. The files in the folder are the following, including the leapTst.py test script:
Leap.dll
Leap.py
Leap.pyc
LeapCSharp.dll
LeapCSharp.NET4.0.dll
leapTst.py
At the beginning of the leapTst.py script I use clr.AddReferenceToFileAndPath and point it to the LeapCSharp.NET4.0.dll assembly inside the folder.
Also in the script, the path to the Leap SDK x64 libraries folder is appended to sys.path to reference the correct libraries.
I then adapted the Sample.py file from the Leap SDK samples folder in Rhino Python to create a custom SampleListener which retrieves frame data from the Leap controller and prints it to the Rhino console.
I noticed that while using the listener callback function and the OnFrame() method to retrieve frame data, Rhino would crash as soon as the listener began ‘listening’ to the incoming stream of data. In order to debug the script I customized the SampleListener class so that it would just return the Frame ID and Timestamp of the current frame from the Leap controller. This is very stable and Rhino does not crash.
As soon as I make the OnFrame method retrun any other frame data, such as the Fingers.TipPosition or HandSphereRadius, then the script crashes Rhino.
Reading the Leap API, there is a note on using the listener callback functions to retrieve frame data that mentions the process is multithreaded and therefore one must ensure that it is run in a threadsafe manner. Could this be the reason why Rhino crashes?
What other methods could be used in Rhino Python (considering that Rhino itself has no inherent application frame rate) to poll the controller for frame data? Timer? Event based polling?
Any help on this would be greatly appreciated. Following is the test script code:
import sys
import clr
import scriptcontext
import rhinoscriptsyntax as rs
import Rhino
import time
clr.AddReferenceToFileAndPath("C:\Users\GMAC\Desktop\leap RHINO test\LeapCSharp.NET4.0.dll")
pathsToLibs = ["C:\\Users\\GMAC\\Documents\\PROJECTS\\CODING\\LEAP MOTION\\LeapDeveloperKit\\LeapDeveloperKit\\LeapSDK\\lib\\x64"]
for path in pathsToLibs:
sys.path.append(path)
print sys.path
import Leap
from Leap import CircleGesture, KeyTapGesture, ScreenTapGesture, SwipeGesture
class SampleListener(Leap.Listener):
def OnInit(self, controller):
print "Initialized"
def OnConnect(self, controller):
print "Connected"
def OnDisconnect(self, controller):
# Note: not dispatched when running in a debugger.
print "Disconnected"
def OnExit(self, controller):
print "Exited"
def OnFrame(self, controller):
# Get the most recent frame and report some basic information
print "This is a frame"
frame = controller.Frame()
print frame
hands = frame.Hands
if hands.Count > 0:
print "Found {} hands".format(hands.Count)
if hands.Count == 1:
hand = hands[0]
Leap.Hand.SphereRadius
handSphereRadius = hand.SphereRadius
handSphereCentre = hand.SphereCentre
print handSphereRadius
print handSphereCentre
def main():
# Create a sample listener and controller
listener = SampleListener()
controller = Leap.Controller()
# Have the sample listener receive events from the controller
controller.AddListener(listener)
# Keep this process running until Enter is pressed
print "Press ESCape to quit..."
running = True
while running:
escape = scriptcontext.escape_test(False)
if escape:
running = False
# Remove the sample listener when done
print "Shutting down"
controller.RemoveListener(listener)
if __name__ == "__main__":
main()