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.
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();
});
On the browser, just include the myo.js
file in your project. Myo
will be global.
On node.js
npm install myo
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.
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();
}
}
});
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)
});
Every event is sent with a timestamp in microseconds. Thus, the full signature of the 'connected' event above, would look like this:
Myo.on('connected', function(data, timestamp){
console.log('connected!', this.id)
});
Of course, declaration of parameters are optional in callbacks.
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();
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.
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')
})
})
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.
Releases are documented in changelog.md
You can use assets provided in our branding and UX guidelines.
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.