Welcome to another Myo Unleashed, the series where we get you set up with 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 myo variable 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 path <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 environment variables:

    # 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 from 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 hub.shutdown but instead returning 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()

Important: The 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.

The myo object you find in the code above is a myo.device_listener.Feed.MyoProxy 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 DeviceListener

The 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.quaternion.Quaternion and myo.vector.Vector objects 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.

Newsletter

Enter your email address and get all latest content delivered to your inbox every now and then.