myo

Javascript bindings for Myo

myo.js

Myo javascript bindings.

Myo.js allows you to interact with Thalmic Labs's Myo Gesture Control Armband using websockets. Listen for IMU, EMG, and gesture events, as well as controlling vibration and locking.

getting started

You'll need a Myo and Myo Connect

var Myo = require('myo');

var myMyo = Myo.create();
myMyo.on('fist', function(edge){
    if(!edge) return;
    console.log('Hello Myo!');
    myMyo.vibrate();
});

installation

On the browser, just include the myo.js file in your project. Myo will be global.

On node.js

npm install myo

experimental features

The Myo is a new kind of device that requires new ways to think about human computer interaction. We'll be sharing some experimental features we're working on. You can use these by including myo.experimental.js. They are not guaranteed to work and may change often. You can read about the experimental features here.

usage

The Myo.js library can be access through the Myo variable. This is the core library and be used to create new Myo instances, trigger global events, amongst other things. To create a new Myo object use the Myo.create() function. This function can two parameters: an id (used for multi-Myo support), and specific options for that Myo.

var myMyo = Myo.create(); //Defaults to id 0
//Make this Myo a bit more sensitive
var thirdMyo = Myo.create(2, {armbusy_threshold : 10});

Commands and events used with these instances are specific to that Myo. You can create Myo instances for Myo that aren't connected yet. For example if your app uses an optional second Myo, create two instances, and listen for the connected event on the second one to enable dual Myo support.

Myo.js is all about events. Whenever we receive data from the Myo, we'll filter through and emit contextual events. You create listeners to these events using the myo.on() function.

myMyo.on('fist', function(edge){
    //Edge is true if it's the start of the pose, false if it's the end of the pose
    if(edge){
        enemies.crush();
    }
});
myMyo.on('gyroscope', function(data){
    if(data.x > 100){
        alert('Woah now!')
    }
});

To reduce the number of false positives, it's useful to react when the user holds a pose, rather than as soon as it's fired. We've provided a handy function, myo.timer() to make writing this as easy as possible. The function takes three parameters: A boolean to turn the timer off and on, a duration in milliseconds, and a function to run.

//After holding thumb to pinky for 1/2 a second, the Myo will be unlocked for 2 seconds
myMyo.on('thumb_to_pinky', function(edge){
    myMyo.timer(edge, 500, function(){
        myMyo.unlock(2000);
    })
});

For more passive apps, it's useful to "lock" and "unlock" the Myo so that accidental actions aren't picked up. We provide .lock() and .unlock() functions, lock and unlock events, and a myo.isLocked boolean. Myo.js doesn't implement any logic for locking and unlocking the Myo, that's up to you.

//Thumb to pinky will unlock the Myo for 2 seconds
// Wave out will make the menu go left, only if the Myo is unlocked,
// also resets the relock for 5 seconds
// The Myo will vibrate on lock and unlock.
myMyo.on('thumb_to_pinky', function(edge){
    myMyo.unlock(2000);
});
myMyo.on('wave_out', function(edge){
    if(edge && !myMyo.isLocked){
        menu.left()
        myMyo.unlock(5000);
    }
});
myMyo.on('unlock', function(){
    myMyo.vibrate();
});
myMyo.on('lock', function(){
    myMyo.vibrate('short').vibrate('short');
});

The Myo now has a built in locking policy. The policy can be set by using .setLockingPolicy. Supported are "none" and "standard". Note that the .lock() call does not lock the Myo if the policy is set to "none"!

//Example for setting locking policy
myo.on('connected', function () {
    myo.setLockingPolicy('none');
});

// Implement your own locking. Example: (Handle locking yourself like described above!!!!)
myo.on('double_tap', function (edge) {
    if(edge){
        if(!myo.isLocked)  {
            console.log("Lock");
            myo.lock();
        }else {
            console.log("Unlock");
            myo.unlock();
        }
    }
});

myo core

options   Myo.options
Here you can review and set the default options that will be used for each Myo instance.

myos   Myo.myos
An array containing the created Myo instances indexed by their id.

create   Myo.create(), Myo.create(id), Myo.create(opts), Myo.create(id, opts)
Creates and returns a new Myo instance. If no id is provided, defaults to 0. opts provided will overwrite the default options.

var myMyo = Myo.create();
var thirdMyo = Myo.create(2, {armbusy_threshold : 10});

on   Myo.on(eventName, callback)
Creates a global listener for each Myo instance for the given event. The callback's context will be the Myo instance.

Myo.on('connected', function(){
    console.log('connected!', this.id)
});

initSocket   Myo.initSocket()
Creates web socket and sets up the message listener. Called implictly whenever you create a new myo instance.

onError   Myo.onError
Myo.onError is triggered whenever Myo.js can't establish a connection to Myo Connect. This could be that it's not running, or that your API version is out of date. You can override this function with a function of your choice.

Myo.onError = function(){
    console.log("Woah, couldn't connect to Myo Connect");
}
Myo.create();

myo data

id   myo.id
Stores the id of the Myo.

connect_verion   myo.connect_verion
Stores the version of Myo Connect.

direction   myo.direction
Stores the direction that the User is wearing the Myo. Can either be "toward_elbow" or "toward_wrist", referencing the Thalmic logo on the device.

arm   myo.arm
Stores which arm the Myo is being worn on. Either "left" or "right"

orientationOffset   myo.orientationOffset
Stores the offset quaternion used with myo.zeroOrientation().

lastIMU   myo.lastIMU
Stores the last IMU object. Useful when you need to look at changes over time.

isConnected   myo.isConnected
Stores a boolean on whether the Myo is currently connected.

isLocked   myo.isLocked
Stores a boolean on whether the Myo is currently locked.

myo functions

on   myo.on(eventName, function(arg1, arg2,...))
On sets up a listener for a specific event name. Whenever that event is triggered, each function added with on(), will be called with whatever arguments trigger() was called with. Returns a unique event id for this listener.

myMyo.on('fist', function(edge){
    if(edge)  console.log('fist pose start');
    if(!edge) console.log('fist pose end');
});

trigger   myo.trigger(eventName, arg1, arg2, ...)
Trigger activates each listener for a specific event. You can add any additional parameters to be passed to the listener. Myo.js uses this internally to trigger events.

myMyo.on('foobar', function(msg){
    console.log('wooooo', msg)
});
myMyo.trigger('foobar', 'ah yis!');

zeroOrientation   myo.zeroOrientation()
When called, where ever the Myo is orientated will now be the origin. This offset value will be stored at myo.orientationOffset.

lock   myo.lock()
Sets Myo.isLocked to true and fires the lock event. Myo.js does nothing with myo.isLocked, it's up to the developer to implement locking features. For example:

myMyo.on('fist', function(edge){
    if(Myo.isLocked || !edge) return;
    Enemies.smash();
});

unlock   myo.unlock(), Myo.unlock(timeout)
Sets Myo.isLocked to false and fires the unlock event. If a timeout is passed in, it will call myo.lock() after the timeout has passed. Subsequient calls will reset the timeout.

myMyo.unlock(); //Will unlock the Myo indefinitely
myMyo.unlock(1000); //Unlocks the Myo, but will relock after 1 second

vibrate   myo.vibrate(), myo.vibrate('short' | 'medium' | 'long')
Makes the Myo vibrate with a given duration. Defaults to 'medium'.

requestBluetoothStrength   myo.requestBluetoothStrength()
Requests the connection strength of the Myo to be sent. Listen to the 'bluetooth_strength' event for the data.

myMyo.on('bluetooth_strength', function(val){
    console.log('Such strength', val);
});
myMyo.requestBluetoothStrength();

streamEMG   myo.streamEMG(enabled)
Tells the Myo to start or stop streaming EMG data. Myo.js must have a connected socket for this to work. Pass nothing or true to enabled it and false to disabled it. Listen to the emg event for the data. Note: while streaming EMG data, gesture recognition might not be at it's best. This is being fixed in the near future.

myMyo.on('connected', function(){
    myMyo.streamEMG(true);
});
myMyo.on('emg', function(data){
    console.log(data);
});

Requests the connection strength of the Myo to be sent. Listen to the 'bluetooth_strength' event for the data.

myMyo.on('bluetooth_strength', function(val){
    console.log('Such strength', val);
});
myMyo.requestBluetoothStrength();

timer   myo.timer(on_off, duration, callback)
Timer is useful for when you want a simple timeout for an action, such as holding a gesture for a period of time. on_off is a boolean that will create or disable the current timer with a duration of duration that will fire the callback.

//Fires a spread_hold event if spread is held for half a second
myMyo.on('fingers_spread', function(edge){
    myMyo.timer(edge, 500, function(){
        myMyo.trigger('spread_hold')
    })
})

events

You can create listeners to the events by using the myo.on() function. You can even fire your own events using myo.trigger().

connected   myo.on('connected', function(){ ... })
Fired when the Myo is successfully connected with the Myo Connect software. Populates myo.connect_version.

disconnected   myo.on('disconnected', function(){ ... })
Fired when the Myo is disconnected from the Myo Connect software.

arm_synced   myo.on('arm_synced', function(){ ... })
Fired when the User puts on the Myo and successfully does the Setup Gesture. Populates myo.arm and myo.direction

arm_unsynced   myo.on('arm_unsynced', function(){ ... })
Fired when the User removes the Myo.

imu   myo.on('imu', function(data){ ... })
This event is fired whenever we receive IMU data from the Myo. This data is grouped like this:

{
    orientation : {
        x : NUM,
        y : NUM,
        z : NUM,
        W : NUM
    },
    gyroscope : {
        x : NUM,
        y : NUM,
        z : NUM
    },
    accelerometer : {
        x : NUM,
        y : NUM,
        z : NUM
    }
}

emg   myo.on('emg', function(data){ ... })
This event is fired whenever we receive EMG data from the Myo. In order to get this data you must first tell the myo you want it to stream EMG by using the myo.streamEMG(true) command. This data is an 8 element array (one for each pod) bounded from -127 to 127.

myMyo.streamEMG(true);
myMyo.on('emg', function(data){
    console.log(data);
});

gyroscope   myo.on('gyroscope', function(data){ ... })
This event is fired whenever we receive gyroscopic data from the Myo. This data is grouped as 3d coordinates.

orientation   myo.on('orientation', function(data){ ... })
This event is fired whenever we receive orientation data from the Myo. This data is grouped as a quanternion.

accelerometer   myo.on('accelerometer', function(data){ ... })
This event is fired whenever we receive acceleration data from the Myo. This data is grouped as 3d coordinates.

bluetooth_strength   myo.on('bluetooth_strength', function(data){ ... })
Fired after Myo.requestBluetoothStrength() is called. Returns a measure of the bluetooth strength the Myo is connected to.

pose   myo.on('pose', function(pose_name, edge){ ... })
Whenever the Myo detects a pose change it will fire a pose event. The listener will be called with the pose_name and the edge which will be true if it is the start of the pose and false if it is the end of the pose. Myo.js will also fire an individual event for each pose with the edge as the only parameter for the listener. Here is a list of all the poses : rest,fingers_spread,wave_in,wave_out,fist,thumb_to_pinky.

Myo.on('pose', function(pose_name, edge){
    if(pose_name != 'rest' && edge){
        console.log('Started ', pose_name);
    }
});
var myMyo = Myo.create();
myMyo.on('wave_in', function(edge){
    if(edge) Menu.left()
})

lock   myo.on('lock', function(){ ... })
Fired whenever myo.lock() is called. Useful for firing vibration events, or updating UI when the Myo becomes locked.

unlock   myo.on('unlock', function(){ ... })
Fired whenever myo.unlock() is called. Useful for firing vibration events, or updating UI when the Myo becomes unlocked.

status   myo.on('status', function(){ ... })
Fired whenever a non-pose, non-IMU, non-EMG event is fired. Useful for making debug windows, without being flooded by IMU events.

changelog

Releases are documented in changelog.md

branding and assets

You can use assets provided in our branding and UX guidelines.

thanks

Thanks to stolksdorf for creating Myo.js

The Myo.js project is licensed using the modified BSD license. For more details, please see LICENSE.txt.