North (formerly Thalmic Labs), the creator of the Myo armband, was acquired by Google in June 2020. Myo sales ended in October 2018 and Myo software, hardware and SDKs are no longer available or supported. Learn more.
Myo Scripting Orientation and Gestures Part Five: Mouse Control Enabled

Part Five: Mouse Control Enabled
We’re nearing the finish line on this tutorial. In part five (parts one, two, three and four here) we’re going to talk about mouse control.
But first, this is what my script looks like at this stage:
scriptId = 'com.thalmic.examples.racethesun'
scriptTitle = "Race The Sun"
scriptDetailsUrl = ""
centreYaw = 0
centreRoll = 0
deltaRoll = 0
YAW_DEADZONE = .1
TWOPI = math.pi * 2
flyingLeft = false
flyingRight = false
printCount = 0
function onForegroundWindowChange(app, title)
myo.debug("onForegroundWindowChange: " .. app .. ", " .. title)
local titleMatch = string.match(title, "Race The Sun") ~= nil or string.match(title, "RaceTheSun") ~= nil
myo.debug("Race the Sun: " .. tostring(titleMatch))
return titleMatch;
end
function onPoseEdge(pose, edge)
myo.debug("onPoseEdge: " .. pose .. ", " .. edge)
if (edge == "on") then
if (pose == "fist") then
centre()
elseif (pose == "fingersSpread") then
escape()
end
end
end
function activeAppName()
return "Race The Sun"
end
function centre()
myo.debug("Centred")
centreYaw = myo.getYaw()
myo.vibrate("short")
end
function escape()
myo.debug("Escape!")
centreYaw = 0
myo.keyboard("escape","press")
end
function onPeriodic()
if (centreYaw == 0) then
return
end
local currentYaw = myo.getYaw()
local currentRoll = myo.getRoll()
local deltaYaw = calculateDeltaRadians(currentYaw, centreYaw)
deltaRoll = calculateDeltaRadians(currentRoll, centreRoll);
printCount = printCount + 1
if printCount >= 200 then
myo.debug("deltaYaw = " .. deltaYaw .. ", centreYaw = " .. centreYaw .. ", currentYaw = " .. currentYaw)
myo.debug("deltaRoll = " .. deltaRoll)
printCount = 0
end
if (deltaYaw > YAW_DEADZONE) then
flyLeft()
elseif (deltaYaw < -YAW_DEADZONE) then
flyRight()
else
flyNeutral()
end
end
function flyLeft()
if (flyingRight) then
myo.debug("Not flying right");
myo.keyboard("right_arrow","up")
flyingRight = false
end
if (not flyingLeft) then
myo.debug("Flying left");
myo.keyboard("left_arrow","down")
flyingLeft = true;
end
end
function flyRight()
if (flyingLeft) then
myo.debug("Not flying left");
myo.keyboard("left_arrow","up")
flyingLeft = false
end
if (not flyingRight) then
myo.debug("Flying right");
myo.keyboard("right_arrow","down")
flyingRight = true
end
end
function flyNeutral()
if (flyingLeft) then
myo.debug("Not flying left");
myo.keyboard("left_arrow","up")
flyingLeft = false
end
if (flyingRight) then
myo.debug("Not flying right");
myo.keyboard("right_arrow","up")
flyingRight = false
end
end
function calculateDeltaRadians(currentYaw, centreYaw)
local deltaYaw = currentYaw - centreYaw
if (deltaYaw > math.pi) then
deltaYaw = deltaYaw - TWOPI
elseif(deltaYaw < -math.pi) then
deltaYaw = deltaYaw + TWOPI
end
return deltaYaw
end
Mouse Control
You know what sucks? Switching between using the Myo armband to play Race The Sun, and then back to the mouse to try and navigate menus or restart the game.
Wouldn’t it be nice to be able to use your Myo to control the mouse?
Yes, Myo Script has cursor control built right in. It’s trivial to enable, too: myo.controlMouse(enabled).
Set that to true in a script and you’ll immediately notice the cursor being moved around by your Myo armband. You will then notice immediately after that there is no way to “lift up” the mouse and center it again, so to move further and further left you will have to start spinning in your chair. The way you solve this is by letting the user turn off mouse control, move their arm, and then turn it back on again.
In other situations you might consider a “clutch” approach where when the user is holding a certain pose the mouse control is disabled, allowing them to recenter their arm. We actually only really want mouse control on in certain situations though, so we’re going to just enable and disable it with the wave out pose. Try that now. Also go ahead and make wave in fire a left click. It’s up to you if you want to switch these based on what arm the user is wearing their Myo on, but a wave in is usually much easier to do without jostling your arm (thereby moving the cursor), so I’m not going to. Remember it should still fire jump (only) on wave “up” or “down”.
You’ll probably find that works pretty well, but you may end up accidentally turning the mouse on while playing the game. Let’s turn this into a timed gesture (i.e. more than just a pose).
Instead, let’s try a hold. We’re going to ask the user to hold the wave out gesture for about 400 milliseconds before we toggle mouse control on or off. We’re nearing the end of our Myo Script tutorials, so see if you can work out how to do that without any more advice.
Need a hint? Try highlighting one of these if you get stuck:
- You’ll need to capture the current time when the user starts double tap
- You can get the current time in milliseconds with myo.getTimeMilliseconds()
- If the user has started wave out, you need to periodically check if the current time is bigger than the double tap start time, plus 400 milliseconds.
- “periodically” means in onPeriodic
- Don’t forget to clear the start time once the mouse is toggled
- What should happen if wave out’s edge is “off”?
- It should also clear the start time
That’s the meat of this script. There are a few more bits of polish we should apply to make it really work well. When mouse control is enabled, the rudder should lose its centre so things don’t go crazy when it’s disabled. You should also make sure the left and right arrows are pressed “up”, or they will break the menus. Fist should disable mouse control in addition to centring the yaw and roll. Once everything is working, you can turn off all the debug output.
Try that now. Tomorrow, we’ll be back in our final part of this tutorial with the complete script and some thoughts on where to go next.
Subscribe to The Lab
Get the latest posts delivered right to your inbox