Table of Contents
This is a copy of the original blog entry posted at developerblog.myo.com.
Welcome to another Myo Unleashed, the series where we get you set up one of the cool tools or bindings made by our awesome developer community This week we have Niklas, who wrote the Myo Python bindings. Take it away, Niklas!
Hey! I’m Niklas Rosenstein, a student at the Technical University of Munich and I make Cinema 4D plugins for a living. I want to show you how you can use the Myo Python bindings! But first, make sure you have the latest Myo SDK downloaded and unarchived.
The bindings are based on ctypes which is a built-in Python module to interface with shared libraries and the Myo SDK provides such a library. They’re compatible with Python 2 and 3 and if you have downloaded the Myo SDK and the Myo Python source, you’re good to go!
First of all, you have to make sure that Myo Python can find the Myo SDK shared library. You have two options to make it possible: Either 1) allow the OS to find it automatically or 2) keep it in a directory of your project/application and tell Myo Python the path to this directory when you initialize it.
# 1) import myo as libmyo libmyo.init() # 2) import myo as libmyo libmyo.init('path/to/myo/library/dir')
Note that I prefer to import the Myo library as
libmyo. The reason for this is that it is very common to have a
myovariable in your code that identifies a Myo armband.
If you choose path 1), it depends on your OS on how to let it find the Myo
shared library. Let’s say that
<MYO_SDK_DIR> is the path to your copy of the
Myo SDK. On Windows, you need to add to your PATH environment variable the
<MYO_SDK_DIR>\bin. On Mac OS on the other hand, you must add to the
DYLD_LIBRARY_PATH variable the path
<MYO_SDK_DIR>/myo.framework. Note that
on Mac OS and on Cygwin, you can use the
~/.bashrc file to export the
# Cygwin export PATH=$PATH:$(cygpath C:\\myo-sdk-win-0.8.1\\bin) # Mac OS export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/niklas/myo-sdk-mac-0.8.1/myo.framework
Now that we’ve got everything set up, let’s get to the code!
Using Myo Python
There are two ways you can use Myo Python: You can either read the data of an armband from a Myo object when you need access to it or you can implement a listener that receives all the data. If possible, you should prefer the listener approach as you are free to ignore data when you don’t need it, but the Myo object must be synchronized and keeps track of all data that comes from the Myo armband.
In either case, you need a
Hub. And when you run the hub, you can either
pass your own
DeviceListener implementation or you pass a
myo.device_listener.Feed which is also just a subclass but allows you to
read the data a proxy object for each Myo armband.
If you’re using your own
DeviceListener implementation, that is all you need
to do. You should make sure to shut down the hub manually at some point in time.
The Hub runs as a non-daemon thread so your program will not exit unless you stop it.
hub = libmyo.Hub() hub.run(1000, listener) try: while hub.running: time.sleep(0.5) except KeyboardInterrupt: print("Quitting...") finally: hub.shutdown()
You might notice that
hub.running part in the while-loop. You can shut down
the hub from your
DeviceListener but not by calling
False from any callback method. Apart from the
DeviceListener thread, you can shut down the hub from any thread.
More on that later.
If you prefer to read the data instead of receiving it or if you’re just lazy,
you can do it like this. The
Feed class provides a convenient method to wait
until a single device is connected!
feed = libmyo.device_listener.Feed() hub = libmyo.Hub() hub.run(1000, feed) try: myo = feed.wait_for_single_device(timeout=10.0) # seconds if not myo: print("No Myo connected after 10 seconds.") sys.exit() while hub.running and myo.connected: quat = myo.orientation print("Orientation:", quat.x, quat.y, quat.z, quat.w) except KeyboardInterrupt: print("Quitting...") finally: hub.shutdown()
wait_for_single_device()method does not return until the timeout is exceeded or a Myo armband is connected. There’s a difference between a paired and a connected Myo.
myo object you find in the code above is a
object which is thread-safe and can be accessed from anywhere. You can use the
Feed.get_connected_devices() to get a list of all connected devices.
Implementing a Device Listener
DeviceListener interface provides callbacks for all Myo event types, you
only have to override method that you need to receive events. Note that the
DeviceListener methods are called from their own thread so you must ensure
appropriate synchronization if you do save the received data somewhere.
class Listener(libmyo.DeviceListener): def on_connect(self, myo, timestamp): print("Hello, Myo!") def on_disconnect(self, myo, timestamp): print("Goodbye, Myo!") def on_orientation_data(self, myo, timestamp, quat): print("Orientation:", quat.x, quat.y, quat.z, quat.w) def on_pose(self, myo, timestamp, pose): if pose == libmyo.Pose.fist: print("Don't show me 'ya fist!") return False # Stops the Hub
Note that Quaternion and Vector data comes in as
myo.vector.Vectorobjects respectively which you can use directly for computations!
So far that is all there is to know to get started with the Myo Python bindings. :) If you have any questions or bug reports, please use the GitHub Issues page or Twitter me @rosensteinn.