I've probably written more Myo Scripts than anyone. But, I've probably only written a completely new script a small handful of times. It's way faster to start from an existing script that's close to what you want, then just pick and choose what you need from it and other examples.

That's a bit of a pain though. There's always going to be some parts you don't need, and if you forget to delete them you can end up with weird bugs or dead code.

So, for the last little while I've been working on a simple template script to start from. If you've been following #MyoCraft closely you'll have seen it's evolution, and in fact the last few scripts were actually based on the template, as sort of a dry run.

Well, now it's ready. If you want to build a Myo Script, start here:



  
scriptId = 'com.thalmic.example.template - CHANGE THIS'  
    scriptTitle = "Template Script - CHANGE scriptTitle & scriptId"  
    scriptDetailsUrl = "https://market.myo.com/app/" -- see http://developerblog.myo.com/how-to-submit-your-application-to-the-myo-market/

    description = [[  
    Template script

    Fill out out! Useful to explain what your connector does  
    but right now it (as well as controls and knownIssuess) is  
    only visible if someone looks at the source code.

    Questions or problems? Talk to us (@thalmicdev)  
    ]]

    controls = [[  
    Controls:  
     - (Optional) Useful to keep things documented
     ]]

    knownIssues = [[  
     - (Optional) Mention any issues
     ]]

    -- Notify the user only when they start their pose
    function notifyUser(edge)  
        if (edge == "down") then
            myo.notifyUserAction()
        end
    end

    function doPerodicThing()  
        -- You can use this to swap out different onPeriodic behaviour for different bindings
    end

    function doFist(edge)  
        notifyUser(edge)
        myo.mouse("left",edge)
    end

    -- Put the function you want to call when the user does a certain pose here
    STANDARD_BINDINGS = {  
        fist            = doFist,
    --    fingersSpread   = someFunction,
    --    waveIn          = someFunction,
    --    waveOut         = someFunction,
    --    doubleTap       = someFunction,
        onPeriodic      = doPerodicThing
    }

    -- If you want to swap in different control schemes, you can do that by changing 'bindings'
    bindings = STANDARD_BINDINGS

    function onActiveChange(isActive)  
        -- Do things that need to happen when your script starts/stops being active

        -- This is the place to unlock the myo and change the locking policy if you want to be unlocked all the time.

        -- Also, cleanup and unpress any buttons that you may have started pressing in the script.
    end

    -- Tell this script when it should be active. Easiest to match against the app package or .exe name
    function onForegroundWindowChange(app, title)  
        app = string.lower(app)
        --myo.debug(title .. ", " .. app)

        return platform == "MacOS" and app == "com.app" or platform == "Windows" and app == "app.exe"
    end

    function activeAppName()  
        return scriptTitle
    end

    function onPeriodic()  
        fn = bindings["onPeriodic"]
        if fn then
            fn()
        end
    end

    function onPoseEdge(pose, edge)  
        --pose = conditionallySwapWave(pose)
        --myo.debug("onPoseEdge: " .. pose .. ": " .. edge)
        if (pose ~= "rest") then
            -- If you are using the standard locking policy, you probably want this on
            -- It will keep Myo from locking in the middle of a pose.
            -- Remove it if you want Myo to be unlocked all the time, or only certain times you control in your script.
            myo.unlock(edge == "on" and "hold" or "timed")
        end
        fn = bindings[pose]
        if fn then
            keyEdge = edge == "off" and "up" or "down"
            fn(keyEdge)
        end
    end

    function conditionallySwapWave(pose)  
        if myo.getArm() == "left" then
            if pose == "waveIn" then
                pose = "waveOut"
            elseif pose == "waveOut" then
                pose = "waveIn"
            end
        end
        return pose
    end

This makes heavy use of function binding. Rather than having a giant onPoseEdge implementation with a big nest of if statements you need to hand craft for every script, you just have a single, simple function. The only reason you'd ever need to look at onPoseEdge is if you aren't using standard locking. If you are using locking policy none or hoping to do an unlock("hold") to keep Myo unlocked for a while, just modify or get rid of this bit:



if (pose ~= "rest") then
            -- If you are using the standard locking policy, you probably want this on
            -- It will keep Myo from locking in the middle of a pose.
            -- Remove it if you want Myo to be unlocked all the time, or only certain times you control in your script.
            myo.unlock(edge == "on" and "hold" or "timed")
        end  

To make something happen when a user does a pose, first you write the function that handles it, then you uncomment the line in STANDARD_BINDINGS for the pose you are interested in, replacing someFunction with the name of the function you just made. The parameter that's passed into your function can be used as the edge parameter for myo.keyboard() or myo.mouse() to let the user press the key as long as they hold the pose.

Oh: Make sure the function is declared BEFORE STANDARD_BINDINGS. So for example, if we wanted to make waveIn and waveOut both press the space bar, you could do something like this:



function jump(edge)  
        notifyUser(edge)
        myo.keyboard("space", edge)
    end

    -- Put the function you want to call when the user does a certain pose here
    STANDARD_BINDINGS = {  
        fist            = doFist,
    --    fingersSpread   = someFunction,
        waveIn          = jump,
        waveOut         = jump,
    --    doubleTap       = someFunction,
        onPeriodic      = doPerodicThing
    }  

There you go! Just take the template and customize it to your needs. It has all the callbacks sketched out so you don't have to look them up, just implement as needed. And don't forget to change the scriptId, scriptTitle, and scriptDetailsUrl!

That's really all there is too it. If you're just joining us, a great place to start is with our Myo Script tutorial series right here, then stay tuned to The Lab and subscribe to our newsletter to keep up to date with all the latest Myo developer tips and information!

If you have any questions, ask in the comments or hit me up on Twitter at @thalmicdev!

Otherwise, good luck, and happy coding!

Newsletter

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