Why and how I used the MYO - sahajss/knowledge_base GitHub Wiki

#What is the MYO The MYO is an armband that uses EMG sensors to measure electrical activity from the users muscles to detect five gestures made by your hansd. It also uses a 9-axis IMU(inertial measurement unit) to sense the motion, orientation, and rotation of the users forearm. The MYO transmits this info over Bluetooth to the computer. ##Why I used it For my project I created a driving simulator using the Oculus and MYO. For my project I needed to use something that could create a realistic driving motion. I was considering the leap motion, but found out that the MYO would be better because it already had pose detection built in and I could use the position information that the MYO provided to make the turning more accurate. #How I used it After doing some researching, I found that I didnt need to connect to the MYO to drive, but could instead just have the MYO acting as a keyboard and using motions and functions to indicate which keys were beng pressed. I then needed to be able to accelerate the car (up arrow), reverse the car(down arrow), reverse the car (space bar), and implement some way of turning the car left and right. ##Accelerating, reversing, and braking To accelerate and reverse the car I needed either the up or down arrow to be held down, but I also needed a way to switch between them realistically. I decided to let the user switch between accelerating and reversing by making a fist. I used this because this is close to the motion they would make when they shift gears. The pose is detected in the inbuilt onPoseEdge function for MYO. The MYO also has a variable called edge, when edge is on that is when the pose is just made, edge being off is when the pose has just stopped being made.

function onPoseEdge(pose, edge)
    if pose == "fist" and edge=="on" then
       currentPlayer:accelrev()
    end	
end

After the user makes a fist and it is detected my function accelrev runs. This function checks whether the user is accelerating or reversing and then switches it so that if they are accelerating and make a fist, they start to reverse. This function also connects the MYO to the keyboard and presses the up or down key based on acceleration or reversing.

function ResearchPlayer:accelrev()
	if(artoggle==0 ) then
		myo.keyboard("down_arrow", "up")
		myo.keyboard("up_arrow", "down")
		myo.debug("accel ")
	elseif(artoggle==1 ) then
		myo.keyboard("down_arrow", "down")
		myo.keyboard("up_arrow", "up")
		myo.debug("rev ")
	end
	artoggle=1-artoggle
end

For some reason using the keyboard("down") function was't working to so fix this I made another function called accelrevtemp() which was the same as accelrev except it didn't change artoggle, I then put this function in the onPeriodic section of the code, which will call it every 10 milliseconds, basically acting as a continuous press of the up/down arrow keys when needed.

function onPeriodic()
    currentPlayer:accelrevtemp()
end

##Turning left and right realistically For turning left and right I wanted to use the position info the MYO provided to detect left and right, and use this to make the user perform a motion similar to a driving wheel. I used the yaw data because yaw is basically how far left and right the user has moved their hand. I first did this by letting the user set a middle point by spreading their fingers and getting the yaw at that point and using this as a middle point for the rest of the time, or until the user reset it. I created two functions called calYaw and calPitch to get the current yaw and pitch of the MYO.

function onPoseEdge(pose, edge)
if pose == "fingersSpread" then
	myo.setLockingPolicy("none");
	myo.debug("setup")
	firstyaw=calYaw()
	firstpitch=calPitch()
end
end

After setting a midpoint I then needed a way of constantly checking for where the users hand is to see if they are left or right of the middle point. I used the inbuilt function of onPeriodic to act as a sort of main method in my code since it runs every 10 millisecond. Here I ran into a problem because instead of returning yaw from 0 to 6 from left to right, the MYO returns yaw like this: left0 -1 -2 -3 3 2 1 0right. To fix this I checked whether the midpoint yaw was negative or positive and based on that I wrote code for each possibility. I also had to make sure that the user had actualy started the game by setting a midpoint so I first checked to make sure that the firstYaw was not 0.

function onPeriodic()
myo.setLockingPolicy("none");
realpitch=myo.getPitch()
realyaw=myo.getYaw()

if firstyaw~=0 then
	if realpitch+.25<firstpitch then
		currentPlayer:stop()
	else
		if firstyaw>0 then
			if realyaw>0 and realyaw<firstyaw then
				currentPlayer:goLeft()
			else
				currentPlayer:goRight()
			end
		else
			if realyaw<0 and realyaw>firstyaw then
				currentPlayer:goRight()
			else
				currentPlayer:goLeft()
			end
		end
	end
end
end