├── .gitignore ├── MyoTest.py ├── PyMyo ├── PyMyo-VisualStudio2012.vcxproj ├── PyMyo.cpp ├── PyMyo.exe ├── PyMyo.pdb ├── README.md ├── Screenshots ├── ConsoleOutputMissingMyo.PNG ├── ConsoleOutputNormal.PNG ├── MyoPythonCode.PNG ├── MyoTestPythonCode.PNG └── PyMyoCppCode.PNG ├── myo.py ├── myo ├── cxx │ ├── DeviceListener.hpp │ ├── Hub.hpp │ ├── Myo.hpp │ ├── Pose.hpp │ ├── Quaternion.hpp │ ├── Vector3.hpp │ ├── detail │ │ └── ThrowOnError.hpp │ └── impl │ │ ├── Hub_impl.hpp │ │ ├── Myo_impl.hpp │ │ └── Pose_impl.hpp ├── libmyo.h ├── libmyo │ └── detail │ │ └── visibility.h └── myo.hpp ├── myo32.dll └── myo64.dll /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | nosetests.xml 35 | coverage.xml 36 | 37 | # Translations 38 | *.mo 39 | 40 | # Mr Developer 41 | .mr.developer.cfg 42 | .project 43 | .pydevproject 44 | 45 | # Rope 46 | .ropeproject 47 | 48 | # Django stuff: 49 | *.log 50 | *.pot 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | -------------------------------------------------------------------------------- /MyoTest.py: -------------------------------------------------------------------------------- 1 | # Test of PyMyo - same functionality as hello-myo.exe 2 | # Paul Lutz 3 | # Scott Martin 4 | 5 | from myo import Myo 6 | import sys 7 | 8 | last_pose = None 9 | 10 | def printData(myo): 11 | global last_pose 12 | 13 | # Rotation is represented by number of stars (as in hello-myo.exe) 14 | (roll_str, pitch_str, yaw_str) = ["*" * int(r) for r in myo.getRotationScaled(18.0)] 15 | 16 | arm_str = myo.getArmString() 17 | 18 | pose_str = myo.getPoseString() 19 | 20 | # Print out the rotation and arm state on the same line each update 21 | sys.stdout.write('\r[{:17s}][{:17s}][{:17s}][{:1s}][{:15s}]'.format( 22 | roll_str, 23 | pitch_str, 24 | yaw_str, 25 | arm_str, 26 | pose_str, 27 | ) 28 | ) 29 | 30 | if (pose_str == "fist") and (last_pose != myo.getPose()): 31 | myo.vibrate(Myo.VIBE_MEDIUM) 32 | 33 | last_pose = myo.getPose() 34 | 35 | def main(): 36 | myMyo = Myo(callback=printData) 37 | myMyo.daemon = True 38 | myMyo.start() 39 | raw_input("Press enter to exit") 40 | 41 | if __name__ == "__main__": 42 | main() -------------------------------------------------------------------------------- /PyMyo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/PyMyo -------------------------------------------------------------------------------- /PyMyo-VisualStudio2012.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {182987B5-A3A5-4847-98A9-0F4079B1A86C} 23 | Win32Proj 24 | PyMyo-VisualStudio2012 25 | 26 | 27 | 28 | Application 29 | true 30 | v110 31 | 32 | 33 | Application 34 | true 35 | v110 36 | 37 | 38 | Application 39 | false 40 | v110 41 | 42 | 43 | Application 44 | false 45 | v110 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | true 65 | hello-myo 66 | 67 | 68 | true 69 | hello-myo 70 | 71 | 72 | true 73 | PyMyo 74 | $(SolutionDir) 75 | $(Configuration)\ 76 | 77 | 78 | true 79 | PyMyo 80 | $(SolutionDir)\ 81 | 82 | 83 | 84 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 85 | MultiThreadedDebugDLL 86 | Level3 87 | ProgramDatabase 88 | Disabled 89 | ..\include 90 | 91 | 92 | true 93 | Console 94 | myo64.lib 95 | ..\lib 96 | 97 | 98 | COPY "..\bin\myo64.dll" "$(OutDir)" && 99 | 100 | Copy required dlls to output directory 101 | 102 | 103 | 104 | 105 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | MultiThreadedDebugDLL 107 | Level3 108 | ProgramDatabase 109 | Disabled 110 | ..\include 111 | 112 | 113 | true 114 | Console 115 | myo32.lib 116 | ..\lib 117 | 118 | 119 | COPY "..\bin\myo32.dll" "$(OutDir)" && 120 | 121 | Copy required dlls to output directory 122 | 123 | 124 | 125 | 126 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 127 | MultiThreadedDLL 128 | Level3 129 | ProgramDatabase 130 | ..\include 131 | 132 | 133 | true 134 | Console 135 | true 136 | true 137 | myo64.lib 138 | ..\lib 139 | 140 | 141 | COPY "..\bin\myo64.dll" "$(OutDir)" && 142 | 143 | Copy required dlls to output directory 144 | 145 | 146 | 147 | 148 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 149 | MultiThreadedDLL 150 | Level3 151 | ProgramDatabase 152 | ..\include 153 | 154 | 155 | true 156 | Console 157 | true 158 | true 159 | myo32.lib 160 | ..\lib 161 | 162 | 163 | COPY "..\bin\myo32.dll" "$(OutDir)" && 164 | 165 | Copy required dlls to output directory 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /PyMyo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | // Modified to expose Myo data to Python 4 | // Paul Lutz 5 | // Scott Martin 6 | // Fabricate.IO 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // Indicates the Myo is not on an arm 13 | #define OFF_ARM 'A' 14 | 15 | // Timeout to raise exception if no myo found 16 | #define FIND_MYO_TIMEOUT_MS 10000 17 | 18 | // Update loop period - 50ms = 20Hz 19 | #define UPDATE_EVENT_PD_MS 50 20 | 21 | // Sizes of rotation & accel arrays 22 | #define QUAT_ARR_SZ 4 23 | #define ACCEL_ARR_SZ 3 24 | 25 | // Receives events from Myo devices 26 | class DataCollector : public myo::DeviceListener { 27 | private: 28 | // Variables to hold current Myo state 29 | bool onArm; 30 | myo::Arm whichArm; 31 | myo::Pose currentPose; 32 | 33 | float quat_arr[QUAT_ARR_SZ]; //stores w, x, y, and z rotation 34 | float accel_arr[ACCEL_ARR_SZ]; 35 | 36 | myo::Myo* myMyo; 37 | std::mutex myoMutex; // Prevents vibration while polling for data 38 | 39 | public: 40 | DataCollector() : onArm(false), currentPose() { 41 | for(int i = 0; i < QUAT_ARR_SZ; i++) { 42 | quat_arr[i] = 0.0; 43 | } 44 | for(int i = 0; i < ACCEL_ARR_SZ; i++) { 45 | accel_arr[i] = 0.0; 46 | } 47 | } 48 | 49 | // This is used later by the vibrator 50 | void setMyo(myo::Myo* myo) { 51 | myMyo = myo; 52 | } 53 | 54 | void setLock(bool lock) { 55 | if (lock) { 56 | myoMutex.lock(); 57 | } else { 58 | myoMutex.unlock(); 59 | } 60 | } 61 | 62 | // Called whenever the Myo device provides its current orientation, which is represented 63 | // as a unit quaternion. 64 | void onOrientationData(myo::Myo* myo, uint64_t timestamp, const myo::Quaternion& quat) { 65 | quat_arr[0] = quat.w(); 66 | quat_arr[1] = quat.x(); 67 | quat_arr[2] = quat.y(); 68 | quat_arr[3] = quat.z(); 69 | } 70 | 71 | // Called whenever the Myo detects that the person wearing it has changed their pose, for example, 72 | // making a fist, or not making a fist anymore. 73 | void onPose(myo::Myo* myo, uint64_t timestamp, myo::Pose pose) { 74 | currentPose = pose; 75 | } 76 | 77 | // Called whenever Myo has recognized a setup gesture after someone has put it on their 78 | // arm. This lets Myo know which arm it's on and which way it's facing. 79 | void onArmRecognized(myo::Myo* myo, uint64_t timestamp, myo::Arm arm, myo::XDirection xDirection) { 80 | onArm = true; 81 | whichArm = arm; 82 | } 83 | 84 | // Called whenever Myo has detected that it was moved from a stable position on a person's arm after 85 | // it recognized the arm. Typically this happens when someone takes Myo off of their arm, but it can also happen 86 | // when Myo is moved around on the arm. 87 | void onArmLost(myo::Myo* myo, uint64_t timestamp) { 88 | onArm = false; 89 | } 90 | 91 | // Called when the Myo sends acceleration data. 92 | void onAccelerometerData (myo::Myo* myo, uint64_t timestamp, const myo::Vector3 &accel) { 93 | accel_arr[0] = accel.x(); 94 | accel_arr[1] = accel.y(); 95 | accel_arr[2] = accel.z(); 96 | } 97 | 98 | // Vibrates the Myo 99 | void vibrate(myo::Myo::VibrationType duration) { 100 | if (!myMyo) { 101 | std::cerr << "Myo not set!"; 102 | exit(2); 103 | } 104 | 105 | myoMutex.lock(); 106 | myMyo->vibrate(duration); 107 | myoMutex.unlock(); 108 | } 109 | 110 | // Prints the current values that were updated by the on...() functions above. 111 | void print() { 112 | 113 | // Prints x, y, and z acceleration of the Myo 114 | for(int i = 0; i < ACCEL_ARR_SZ; i++) { 115 | char* bits = reinterpret_cast(&accel_arr[i]); 116 | for(int n = 0; n < sizeof(float); ++n) { 117 | std::cout << (bits[n]); 118 | } 119 | } 120 | 121 | // Prints w, x, y, and z rotation of the Myo 122 | for(int i = 0; i < QUAT_ARR_SZ; i++) { 123 | char* bits = reinterpret_cast(&quat_arr[i]); 124 | for(int n = 0; n < sizeof(float); ++n) { 125 | std::cout << (bits[n]); 126 | } 127 | } 128 | 129 | // Prints Pose byte 130 | unsigned char poseByte; 131 | poseByte = currentPose.type() & 0xFF; 132 | std::cout << poseByte; 133 | 134 | // Prints which arm the Myo is on: 0 = right, 1 = left 135 | if(onArm) { 136 | std::cout << (unsigned char)whichArm; 137 | } else { 138 | std::cout << OFF_ARM; 139 | } 140 | 141 | std::cout << '\n'; 142 | std::cout << std::flush; // Prevent caching multiple lines so each line is written immediately 143 | } 144 | }; 145 | DataCollector collector; 146 | 147 | // Reads integer values from the console to control vibration 148 | void inputThread() { 149 | std::string input; 150 | while(true) { 151 | std::cin >> input; 152 | if(std::cin.fail()) { 153 | std::exit(0); 154 | } 155 | 156 | collector.vibrate((myo::Myo::VibrationType)input[0]); 157 | } 158 | } 159 | 160 | int main(int argc, char** argv) 161 | { 162 | try { 163 | myo::Hub hub("com.fabricate.pyo"); // This provides access to one or more Myos. 164 | 165 | myo::Myo* myo = hub.waitForMyo(FIND_MYO_TIMEOUT_MS); 166 | if (!myo) { 167 | throw std::runtime_error("Unable to find a Myo!"); 168 | } 169 | collector.setMyo(myo); // Used as a reference for vibration 170 | hub.addListener(&collector); // Tell the hub to send data events to the collector 171 | 172 | // This thread reads vibration commands 173 | std::thread t1 (inputThread); 174 | t1.detach(); 175 | 176 | while (true) { 177 | collector.setLock(true); // Prevent vibration thread from writing while we read 178 | hub.run(UPDATE_EVENT_PD_MS); // Allow myo to push events at the given rate 179 | collector.setLock(false); 180 | collector.print(); 181 | } 182 | } catch (const std::exception& e) { 183 | std::cerr << "Error: " << e.what() << std::endl; 184 | return 1; 185 | } 186 | } -------------------------------------------------------------------------------- /PyMyo.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/PyMyo.exe -------------------------------------------------------------------------------- /PyMyo.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/PyMyo.pdb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MYO-python 2 | ========== 3 | 4 | MYO armband wrapped with python! 5 | -------------------------------------------------------------------------------- /Screenshots/ConsoleOutputMissingMyo.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/Screenshots/ConsoleOutputMissingMyo.PNG -------------------------------------------------------------------------------- /Screenshots/ConsoleOutputNormal.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/Screenshots/ConsoleOutputNormal.PNG -------------------------------------------------------------------------------- /Screenshots/MyoPythonCode.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/Screenshots/MyoPythonCode.PNG -------------------------------------------------------------------------------- /Screenshots/MyoTestPythonCode.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/Screenshots/MyoTestPythonCode.PNG -------------------------------------------------------------------------------- /Screenshots/PyMyoCppCode.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/Screenshots/PyMyoCppCode.PNG -------------------------------------------------------------------------------- /myo.py: -------------------------------------------------------------------------------- 1 | # Communicates with PyMyo.exe to enable Python support of Myo armband 2 | # Paul Lutz 3 | # Scott Martin 4 | # Fabricate.IO 5 | 6 | import time 7 | import subprocess 8 | import sys 9 | import struct 10 | import math 11 | import threading 12 | import platform 13 | 14 | class Myo(threading.Thread): 15 | """ Wrapper for PyMyo.exe - handles event data via callback, and can vibrate the myo """ 16 | 17 | POSES = { 18 | 0 : "rest", 19 | 1 : "fist", 20 | 2 : "waveIn", 21 | 3 : "waveOut", 22 | 4 : "fingersSpread", 23 | 5 : "reserved1", 24 | 6 : "thumbToPinky", 25 | } 26 | OSCOMMANDS = { 27 | "Darwin" : "./PyMyo", 28 | "Windows": "PyMyo.exe", 29 | } 30 | # These durations are specified by Thalmic 31 | VIBE_LONG = 2 32 | VIBE_MEDIUM = 1 33 | VIBE_SHORT = 0 34 | 35 | cmd = "nope" 36 | 37 | # PyMyo.exe prints a packet (followed by a newline) every time the myo has new event data 38 | PACKET_LEN = 30 39 | PACKET_FORMAT = "fffffffBB" 40 | 41 | def __init__(self, callback): 42 | threading.Thread.__init__(self) 43 | 44 | self.cmd = self.OSCOMMANDS.get(platform.system()) 45 | 46 | self.proc = subprocess.Popen(self.cmd, bufsize=0, stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) 47 | 48 | self.pose = None 49 | self.quat = None 50 | self.rot = None 51 | self.accel = None 52 | 53 | self.callback = callback 54 | 55 | def run(self): 56 | while True: 57 | # This will hang until the next data event is read 58 | newdata = self.proc.stdout.readline().strip() 59 | if len(newdata) != Myo.PACKET_LEN: 60 | continue 61 | 62 | # Extract data from the packet 63 | data = struct.unpack(Myo.PACKET_FORMAT,newdata) 64 | (self.accel, self.quat, self.pose, self.which_arm) = (data[0:3], data[3:7], data[7], data[8]) 65 | 66 | # Update Euler rotation if valid 67 | self.rot = self.calculateEuler(self.quat) or self.rot 68 | 69 | # Callback to user code 70 | self.callback(self) 71 | 72 | def calculateEuler(self, quat): 73 | # Convert quaternion to (roll, pitch, yaw) rotation 74 | (w, x, y, z) = quat 75 | try: 76 | roll = math.atan2(2*y*w - 2*x*z, 1 - 2*y*y - 2*z*z) 77 | pitch = math.atan2(2*x*w - 2*y*z, 1 - 2*x*x - 2*z*z) 78 | yaw = math.asin(2*x*y + 2*z*w) 79 | return (roll, pitch, yaw) 80 | except: 81 | return None 82 | 83 | def vibrate(self, duration): 84 | # Vibrates the Myo (must be one of VIBE_*) 85 | assert duration in [Myo.VIBE_LONG, Myo.VIBE_MEDIUM, Myo.VIBE_SHORT] 86 | self.proc.stdin.write(chr(1) + "\n") 87 | self.proc.stdin.flush() 88 | 89 | def getAcceleration(self): 90 | # Return [x, y, z] acceleration 91 | return self.accel 92 | 93 | def getRotation(self): 94 | # Return [roll, pitch, yaw] 95 | return self.rot 96 | 97 | def getRotationScaled(self, scale): 98 | # Returns [x, y, z] accel scaled between 0 and scale. 99 | return [(x+math.pi)/(math.pi*2.0)*scale for x in self.rot] 100 | 101 | def getArm(self): 102 | # Returns 0 for right arm, 1 for left arm 103 | return self.which_arm 104 | 105 | def getArmString(self): 106 | # Return "R" for right arm, "L" for left arm, or "?" if no arm 107 | return { 108 | 0: "R", 109 | 1: "L" 110 | }.get(self.getArm(), "?") 111 | 112 | def getPoseString(self): 113 | # Return string representing pose, or "unknown" if unknown 114 | return self.POSES.get(self.getPose(), "unknown") 115 | 116 | def getPose(self): 117 | # Return integer pose state 118 | return self.pose 119 | -------------------------------------------------------------------------------- /myo/cxx/DeviceListener.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_DEVICELISTENER_HPP 4 | #define MYO_CXX_DEVICELISTENER_HPP 5 | 6 | #include 7 | 8 | #include "Pose.hpp" 9 | 10 | namespace myo { 11 | 12 | class Myo; 13 | template 14 | class Quaternion; 15 | template 16 | class Vector3; 17 | 18 | /// Enumeration identifying a right arm or left arm. 19 | enum Arm { 20 | armLeft = libmyo_arm_left, 21 | armRight = libmyo_arm_right, 22 | armUnknown = libmyo_arm_unknown 23 | }; 24 | 25 | /// Possible directions for Myo's +x axis relative to a user's arm. 26 | enum XDirection { 27 | xDirectionTowardWrist = libmyo_x_direction_toward_wrist, 28 | xDirectionTowardElbow = libmyo_x_direction_toward_elbow, 29 | xDirectionUnknown = libmyo_x_direction_unknown 30 | }; 31 | 32 | /// Firmware version of Myo. 33 | struct FirmwareVersion { 34 | unsigned int firmwareVersionMajor; ///< Myo's major version must match the required major version. 35 | unsigned int firmwareVersionMinor; ///< Myo's minor version must match the required minor version. 36 | unsigned int firmwareVersionPatch; ///< Myo's patch version must greater or equal to the required patch version. 37 | unsigned int firmwareVersionHardwareRev; ///< Myo's hardware revision; not used to detect firmware version mismatch. 38 | }; 39 | 40 | /// A DeviceListener receives events about a Myo. 41 | /// @see Hub::addListener() 42 | class DeviceListener { 43 | public: 44 | virtual ~DeviceListener() {} 45 | 46 | /// Called when a Myo has been paired. 47 | virtual void onPair(Myo* myo, uint64_t timestamp, FirmwareVersion firmwareVersion) {} 48 | 49 | /// Called when a paired Myo has been connected. 50 | virtual void onConnect(Myo* myo, uint64_t timestamp, FirmwareVersion firmwareVersion) {} 51 | 52 | /// Called when a paired Myo has been disconnected. 53 | virtual void onDisconnect(Myo* myo, uint64_t timestamp) {} 54 | 55 | /// Called when a paired Myo recognizes that it is on an arm. 56 | virtual void onArmRecognized(Myo* myo, uint64_t timestamp, Arm arm, XDirection xDirection) {} 57 | 58 | /// Called when a paired Myo is moved or removed from the arm. 59 | virtual void onArmLost(Myo* myo, uint64_t timestamp) {} 60 | 61 | /// Called when a paired Myo has provided a new pose. 62 | virtual void onPose(Myo* myo, uint64_t timestamp, Pose pose) {} 63 | 64 | /// Called when a paired Myo has provided new orientation data. 65 | virtual void onOrientationData(Myo* myo, uint64_t timestamp, const Quaternion& rotation) {} 66 | 67 | /// Called when a paired Myo has provided new accelerometer data in units of g. 68 | virtual void onAccelerometerData(Myo* myo, uint64_t timestamp, const Vector3& accel) {} 69 | 70 | /// Called when a paired Myo has provided new gyroscope data in units of deg/s. 71 | virtual void onGyroscopeData(Myo* myo, uint64_t timestamp, const Vector3& gyro) {} 72 | 73 | /// Called when a paired Myo has provided a new RSSI value. 74 | /// @see Myo::requestRssi() to request an RSSI value from the Myo. 75 | virtual void onRssi(Myo* myo, uint64_t timestamp, int8_t rssi) {} 76 | 77 | /// @cond LIBMYO_INTERNALS 78 | 79 | virtual void onOpaqueEvent(libmyo_event_t) {} 80 | 81 | /// @endcond 82 | }; 83 | 84 | } // namespace myo 85 | 86 | #endif // MYO_CXX_DEVICELISTENER_HPP 87 | -------------------------------------------------------------------------------- /myo/cxx/Hub.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_HUB_HPP 4 | #define MYO_CXX_HUB_HPP 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace myo { 11 | 12 | class Myo; 13 | class DeviceListener; 14 | 15 | /// @brief A Hub provides access to one or more Myo instances. 16 | class Hub { 17 | public: 18 | /// Construct a hub. 19 | /// \a applicationIdentifier must follow a reverse domain name format (ex. com.domainname.appname). Application 20 | /// identifiers can be formed from the set of alphanumeric ASCII characters (a-z, A-Z, 0-9). The hyphen (-) and 21 | /// underscore (_) characters are permitted if they are not adjacent to a period (.) character (i.e. not at the 22 | /// start or end of each segment), but are not permitted in the top-level domain. Application identifiers must have 23 | /// three or more segments. For example, if a company's domain is example.com and the application is named 24 | /// hello-world, one could use "com.example.hello-world" as a valid application identifier. \a applicationIdentifier 25 | /// can be an empty string. 26 | /// Throws an exception of type std::invalid_argument if \a applicationIdentifier is not in the proper reverse 27 | /// domain name format or is longer than 255 characters. 28 | /// Throws an exception of type std::runtime_error if the hub initialization failed for some reason, typically 29 | /// because Myo Connect is not running and a connection can thus not be established. 30 | Hub(const std::string& applicationIdentifier = ""); 31 | 32 | /// Deallocate any resources associated with a Hub. 33 | /// This will cause all Myo instances retrieved from this Hub to become invalid. 34 | ~Hub(); 35 | 36 | /// Wait for a Myo to become paired, or time out after \a timeout_ms milliseconds if provided. 37 | /// If \a timeout_ms is zero, this function blocks until a Myo is found. 38 | /// This function must not be called concurrently with run() or runOnce(). 39 | Myo* waitForMyo(unsigned int milliseconds = 0); 40 | 41 | /// Register a listener to be called when device events occur. 42 | void addListener(DeviceListener* listener); 43 | 44 | /// Remove a previously registered listener. 45 | void removeListener(DeviceListener* listener); 46 | 47 | /// Run the event loop for the specified duration (in milliseconds). 48 | void run(unsigned int duration_ms); 49 | 50 | /// Run the event loop until a single event occurs, or the specified duration (in milliseconds) has elapsed. 51 | void runOnce(unsigned int duration_ms); 52 | 53 | /// @cond MYO_INTERNALS 54 | 55 | /// Return the internal libmyo object corresponding to this hub. 56 | libmyo_hub_t libmyoObject(); 57 | 58 | protected: 59 | void onDeviceEvent(libmyo_event_t event); 60 | 61 | Myo* lookupMyo(libmyo_myo_t opaqueMyo) const; 62 | 63 | Myo* addMyo(libmyo_myo_t opaqueMyo); 64 | 65 | libmyo_hub_t _hub; 66 | std::vector _myos; 67 | std::vector _listeners; 68 | 69 | /// @endcond 70 | 71 | private: 72 | // Not implemented 73 | Hub(const Hub&); 74 | Hub& operator=(const Hub&); 75 | }; 76 | 77 | /// @example hello-myo.cpp 78 | 79 | } // namespace myo 80 | 81 | #include "impl/Hub_impl.hpp" 82 | 83 | #endif // MYO_CXX_HUB_HPP 84 | -------------------------------------------------------------------------------- /myo/cxx/Myo.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_MYO_HPP 4 | #define MYO_CXX_MYO_HPP 5 | 6 | #include 7 | 8 | namespace myo { 9 | 10 | /// Represents a Myo device with a specific MAC address. 11 | /// This class can not be instantiated directly; instead, use Hub to get access to a Myo. 12 | /// There is only one Myo instance corresponding to each device; thus, if the addresses of two Myo instances compare 13 | /// equal, they refer to the same device. 14 | class Myo { 15 | public: 16 | /// Types of vibration supported by the Myo. 17 | enum VibrationType { 18 | vibrationShort = libmyo_vibration_short, 19 | vibrationMedium = libmyo_vibration_medium, 20 | vibrationLong = libmyo_vibration_long 21 | }; 22 | 23 | /// Vibrate the Myo. 24 | void vibrate(VibrationType type); 25 | 26 | /// Request the RSSI of the Myo. An onRssi event will likely be generated with the value of the RSSI. 27 | /// @see DeviceListener::onRssi() 28 | void requestRssi() const; 29 | 30 | /// @cond MYO_INTERNALS 31 | 32 | /// Return the internal libmyo object corresponding to this device. 33 | libmyo_myo_t libmyoObject() const; 34 | 35 | /// @endcond 36 | 37 | private: 38 | Myo(libmyo_myo_t myo); 39 | ~Myo(); 40 | 41 | libmyo_myo_t _myo; 42 | 43 | // Not implemented. 44 | Myo(const Myo&); 45 | Myo& operator=(const Myo&); 46 | 47 | friend class Hub; 48 | }; 49 | 50 | } // namespace myo 51 | 52 | #include "impl/Myo_impl.hpp" 53 | 54 | #endif // MYO_CXX_MYO_HPP 55 | -------------------------------------------------------------------------------- /myo/cxx/Pose.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_POSE_HPP 4 | #define MYO_CXX_POSE_HPP 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace myo { 12 | 13 | /// A pose represents a detected configuration of the user's hand. 14 | class Pose { 15 | public: 16 | /// Types of poses supported by the SDK. 17 | enum Type { 18 | rest = libmyo_pose_rest, 19 | fist = libmyo_pose_fist, 20 | waveIn = libmyo_pose_wave_in, 21 | waveOut = libmyo_pose_wave_out, 22 | fingersSpread = libmyo_pose_fingers_spread, 23 | reserved1 = libmyo_pose_reserved1, 24 | thumbToPinky = libmyo_pose_thumb_to_pinky, 25 | unknown = libmyo_pose_unknown 26 | }; 27 | 28 | /// Construct a pose of type Pose::none. 29 | Pose(); 30 | 31 | /// Construct a pose with the given type. 32 | Pose(Type type); 33 | 34 | /// Returns true if and only if the two poses are of the same type. 35 | bool operator==(Pose other) const; 36 | 37 | /// Equivalent to `!(*this == other)`. 38 | bool operator!=(Pose other) const; 39 | 40 | /// Returns the type of this pose. 41 | Type type() const; 42 | 43 | /// Return a human-readable string representation of the pose. 44 | std::string toString() const; 45 | 46 | private: 47 | Type _type; 48 | }; 49 | 50 | /// @relates Pose 51 | /// Returns true if and only if the type of pose is the same as the provided type. 52 | bool operator==(Pose pose, Pose::Type t); 53 | 54 | /// @relates Pose 55 | /// Equivalent to `pose == type`. 56 | bool operator==(Pose::Type type, Pose pose); 57 | 58 | /// @relates Pose 59 | /// Equivalent to `!(pose == type)`. 60 | bool operator!=(Pose pose, Pose::Type type); 61 | 62 | /// @relates Pose 63 | /// Equivalent to `!(type == pose)`. 64 | bool operator!=(Pose::Type type, Pose pose); 65 | 66 | /// @relates Pose 67 | /// Write the name of the provided pose to the provided output stream. 68 | std::ostream& operator<<(std::ostream& out, const Pose& pose); 69 | 70 | } // namespace myo 71 | 72 | #include "impl/Pose_impl.hpp" 73 | 74 | #endif // MYO_CXX_POSE_HPP 75 | -------------------------------------------------------------------------------- /myo/cxx/Quaternion.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_QUATERNION_HPP 4 | #define MYO_CXX_QUATERNION_HPP 5 | 6 | #include 7 | 8 | #include "Vector3.hpp" 9 | 10 | namespace myo { 11 | 12 | /// A quaternion that can be used to represent a rotation. 13 | /// This type provides only very basic functionality to store quaternions that's sufficient to retrieve the data to 14 | /// be placed in a full featured quaternion type. 15 | template 16 | class Quaternion { 17 | public: 18 | /// Construct a quaternion that represents zero rotation (i.e. the multiplicative identity). 19 | Quaternion() 20 | : _x(0) 21 | , _y(0) 22 | , _z(0) 23 | , _w(1) 24 | { 25 | } 26 | 27 | /// Construct a quaternion with the provided components. 28 | Quaternion(T x, T y, T z, T w) 29 | : _x(x) 30 | , _y(y) 31 | , _z(z) 32 | , _w(w) 33 | { 34 | } 35 | 36 | /// Set the components of this quaternion to be those of the other. 37 | Quaternion& operator=(const Quaternion other) 38 | { 39 | _x = other._x; 40 | _y = other._y; 41 | _z = other._z; 42 | _w = other._w; 43 | 44 | return *this; 45 | } 46 | 47 | /// Return the x-component of this quaternion's vector. 48 | T x() const { return _x; } 49 | 50 | /// Return the y-component of this quaternion's vector. 51 | T y() const { return _y; } 52 | 53 | /// Return the z-component of this quaternion's vector. 54 | T z() const { return _z; } 55 | 56 | /// Return the w-component (scalar) of this quaternion. 57 | T w() const { return _w; } 58 | 59 | /// Return the quaternion multiplied by \a rhs. 60 | /// Note that quaternion multiplication is not commutative. 61 | Quaternion operator*(const Quaternion& rhs) const 62 | { 63 | return Quaternion( 64 | _w * rhs._x + _x * rhs._w + _y * rhs._z - _z * rhs._y, 65 | _w * rhs._y - _x * rhs._z + _y * rhs._w + _z * rhs._x, 66 | _w * rhs._z + _x * rhs._y - _y * rhs._x + _z * rhs._w, 67 | _w * rhs._w - _x * rhs._x - _y * rhs._y - _z * rhs._z 68 | ); 69 | } 70 | 71 | /// Multiply this quaternion by \a rhs. 72 | /// Return this quaternion updated with the result. 73 | Quaternion& operator*=(const Quaternion& rhs) 74 | { 75 | *this = *this * rhs; 76 | return *this; 77 | } 78 | 79 | /// Return the unit quaternion corresponding to the same rotation as this one. 80 | Quaternion normalized() const 81 | { 82 | T magnitude = std::sqrt(_x * _x + _y * _y + _z * _z + _w * _w); 83 | 84 | return Quaternion(_x / magnitude, _y / magnitude, _z / magnitude, _w / magnitude); 85 | } 86 | 87 | /// Return this quaternion's conjugate. 88 | Quaternion conjugate() const 89 | { 90 | return Quaternion(-_x, -_y, -_z, _w); 91 | } 92 | 93 | /// Return a quaternion that represents a right-handed rotation of \a angle radians about the given \a axis. 94 | /// \a axis The unit vector representing the axis of rotation. 95 | /// \a angle The angle of rotation, in radians. 96 | static Quaternion fromAxisAngle(const myo::Vector3& axis, T angle) 97 | { 98 | return Quaternion(axis.x() * std::sin(angle / 2), 99 | axis.y() * std::sin(angle / 2), 100 | axis.z() * std::sin(angle / 2), 101 | std::cos(angle / 2)); 102 | } 103 | 104 | private: 105 | T _x, _y, _z, _w; 106 | }; 107 | 108 | /// Return a copy of this \a vec rotated by \a quat. 109 | /// \relates myo::Quaternion 110 | template 111 | Vector3 rotate(const Quaternion& quat, const Vector3& vec) 112 | { 113 | myo::Quaternion qvec(vec.x(), vec.y(), vec.z(), 0); 114 | myo::Quaternion result = quat * qvec * quat.conjugate(); 115 | return Vector3(result.x(), result.y(), result.z()); 116 | } 117 | 118 | } // namespace myo 119 | 120 | #endif // MYO_CXX_QUATERNION_HPP 121 | -------------------------------------------------------------------------------- /myo/cxx/Vector3.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_VECTOR3_HPP 4 | #define MYO_CXX_VECTOR3_HPP 5 | 6 | #define _USE_MATH_DEFINES 7 | #include 8 | 9 | namespace myo { 10 | 11 | /// A vector of three components. 12 | /// This type provides very basic functionality to store a three dimensional vector that's sufficient to retrieve 13 | /// the data to be placed in a full featured vector type. A few common vector operations, such as dot product and 14 | /// cross product, are also provided. 15 | template 16 | class Vector3 { 17 | public: 18 | /// Construct a vector of all zeroes. 19 | Vector3() 20 | { 21 | _data[0] = 0; 22 | _data[1] = 0; 23 | _data[2] = 0; 24 | } 25 | 26 | /// Construct a vector with the three provided components. 27 | Vector3(T x, T y, T z) 28 | { 29 | _data[0] = x; 30 | _data[1] = y; 31 | _data[2] = z; 32 | } 33 | 34 | /// Construct a vector with the same components as \a other. 35 | Vector3(const Vector3& other) 36 | { 37 | *this = other; 38 | } 39 | 40 | /// Set the components of this vector to be the same as \a other. 41 | Vector3& operator=(const Vector3& other) 42 | { 43 | _data[0] = other._data[0]; 44 | _data[1] = other._data[1]; 45 | _data[2] = other._data[2]; 46 | 47 | return *this; 48 | } 49 | 50 | /// Return a copy of the component of this vector at \a index, which should be 0, 1, or 2. 51 | T operator[](unsigned int index) const 52 | { 53 | return _data[index]; 54 | } 55 | 56 | /// Return the x-component of this vector. 57 | T x() const { return _data[0]; } 58 | 59 | /// Return the y-component of this vector. 60 | T y() const { return _data[1]; } 61 | 62 | /// Return the z-component of this vector. 63 | T z() const { return _data[2]; } 64 | 65 | /// Return the magnitude of this vector. 66 | T magnitude() const 67 | { 68 | return std::sqrt(x() * x() + y() * y() + z() * z()); 69 | } 70 | 71 | /// Return a normalized copy of this vector. 72 | Vector3 normalized() const 73 | { 74 | T norm = magnitude(); 75 | return Vector3(x() / norm, y() / norm, z() / norm); 76 | } 77 | 78 | /// Return the dot product of this vector and \a rhs. 79 | T dot(const Vector3& rhs) const 80 | { 81 | return x() * rhs.x() + y() * rhs.y() + z() * rhs.z(); 82 | } 83 | 84 | /// Return the cross product of this vector and \a rhs. 85 | Vector3 cross(const Vector3& rhs) const 86 | { 87 | return Vector3( 88 | y() * rhs.z() - z() * rhs.y(), 89 | z() * rhs.x() - x() * rhs.z(), 90 | x() * rhs.y() - y() * rhs.x() 91 | ); 92 | } 93 | 94 | /// Return the angle between this vector and \a rhs, in radians. 95 | T angleTo(const Vector3& rhs) const 96 | { 97 | return std::acos(dot(rhs) / (magnitude() * rhs.magnitude())); 98 | } 99 | 100 | private: 101 | T _data[3]; 102 | }; 103 | 104 | } // namespace myo 105 | 106 | #endif // MYO_CXX_VECTOR3_HPP 107 | -------------------------------------------------------------------------------- /myo/cxx/detail/ThrowOnError.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_DETAIL_THROWONERROR_HPP 4 | #define MYO_CXX_DETAIL_THROWONERROR_HPP 5 | 6 | #include 7 | 8 | #include 9 | 10 | #if defined(_MSC_VER) && _MSC_VER <= 1800 11 | #define LIBMYO_NOEXCEPT(b) 12 | #else 13 | #if __cplusplus >= 201103L 14 | # define LIBMYO_NOEXCEPT(b) noexcept(b) 15 | #else 16 | # define LIBMYO_NOEXCEPT(b) 17 | #endif 18 | #endif 19 | 20 | namespace myo { 21 | 22 | class ThrowOnError { 23 | public: 24 | ThrowOnError() 25 | : _error() 26 | { 27 | } 28 | 29 | ~ThrowOnError() LIBMYO_NOEXCEPT(false) 30 | { 31 | if (_error) 32 | { 33 | switch (libmyo_error_kind(_error)) { 34 | case libmyo_error: 35 | case libmyo_error_runtime: 36 | { 37 | std::runtime_error exception(libmyo_error_cstring(_error)); 38 | libmyo_free_error_details(_error); 39 | throw exception; 40 | } 41 | case libmyo_error_invalid_argument: 42 | { 43 | std::invalid_argument exception(libmyo_error_cstring(_error)); 44 | libmyo_free_error_details(_error); 45 | throw exception; 46 | } 47 | case libmyo_success: 48 | { 49 | break; 50 | } 51 | } 52 | } 53 | } 54 | 55 | operator libmyo_error_details_t*() 56 | { 57 | return &_error; 58 | } 59 | 60 | private: 61 | libmyo_error_details_t _error; 62 | 63 | // Not implemented 64 | ThrowOnError(const ThrowOnError&); // = delete; 65 | ThrowOnError& operator=(const ThrowOnError&); // = delete; 66 | }; 67 | 68 | } //namespace libmyo 69 | 70 | #endif // MYO_CXX_DETAIL_THROWONERROR_HPP 71 | -------------------------------------------------------------------------------- /myo/cxx/impl/Hub_impl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #include "../Hub.hpp" 4 | 5 | #include 6 | #include 7 | 8 | #include "../DeviceListener.hpp" 9 | #include "../Myo.hpp" 10 | #include "../Pose.hpp" 11 | #include "../Quaternion.hpp" 12 | #include "../Vector3.hpp" 13 | #include "../detail/ThrowOnError.hpp" 14 | 15 | namespace myo { 16 | 17 | inline 18 | Hub::Hub(const std::string& applicationIdentifier) 19 | : _hub(0) 20 | , _myos() 21 | , _listeners() 22 | { 23 | libmyo_init_hub(&_hub, applicationIdentifier.c_str(), ThrowOnError()); 24 | } 25 | 26 | inline 27 | Hub::~Hub() 28 | { 29 | for (std::vector::iterator I = _myos.begin(), IE = _myos.end(); I != IE; ++I) { 30 | delete *I; 31 | } 32 | libmyo_shutdown_hub(_hub, 0); 33 | } 34 | 35 | inline 36 | Myo* Hub::waitForMyo(unsigned int timeout_ms) 37 | { 38 | std::size_t prevSize = _myos.size(); 39 | 40 | struct local { 41 | static libmyo_handler_result_t handler(void* user_data, libmyo_event_t event) { 42 | Hub* hub = static_cast(user_data); 43 | 44 | libmyo_myo_t opaque_myo = libmyo_event_get_myo(event); 45 | 46 | switch (libmyo_event_get_type(event)) { 47 | case libmyo_event_paired: 48 | hub->addMyo(opaque_myo); 49 | return libmyo_handler_stop; 50 | default: 51 | break; 52 | } 53 | 54 | return libmyo_handler_continue; 55 | } 56 | }; 57 | 58 | do { 59 | libmyo_run(_hub, timeout_ms ? timeout_ms : 1000, &local::handler, this, ThrowOnError()); 60 | } while (!timeout_ms && _myos.empty()); 61 | 62 | if (_myos.size() <= prevSize) { 63 | return 0; 64 | } 65 | 66 | return _myos.back(); 67 | } 68 | 69 | inline 70 | void Hub::addListener(DeviceListener* listener) 71 | { 72 | if (std::find(_listeners.begin(), _listeners.end(), listener) != _listeners.end()) { 73 | // Listener was already added. 74 | return; 75 | } 76 | _listeners.push_back(listener); 77 | } 78 | 79 | inline 80 | void Hub::removeListener(DeviceListener* listener) 81 | { 82 | std::vector::iterator I = std::find(_listeners.begin(), _listeners.end(), listener); 83 | if (I == _listeners.end()) { 84 | // Don't have this listener. 85 | return; 86 | } 87 | 88 | _listeners.erase(I); 89 | } 90 | 91 | inline 92 | void Hub::onDeviceEvent(libmyo_event_t event) 93 | { 94 | libmyo_myo_t opaqueMyo = libmyo_event_get_myo(event); 95 | 96 | Myo* myo = lookupMyo(opaqueMyo); 97 | 98 | if (!myo && libmyo_event_get_type(event) == libmyo_event_paired) { 99 | myo = addMyo(opaqueMyo); 100 | } 101 | 102 | if (!myo) { 103 | // Ignore events for Myos we don't know about. 104 | return; 105 | } 106 | 107 | for (std::vector::iterator I = _listeners.begin(), IE = _listeners.end(); I != IE; ++I) { 108 | DeviceListener* listener = *I; 109 | 110 | listener->onOpaqueEvent(event); 111 | 112 | uint64_t time = libmyo_event_get_timestamp(event); 113 | 114 | switch (libmyo_event_get_type(event)) { 115 | case libmyo_event_paired: { 116 | FirmwareVersion version = {libmyo_event_get_firmware_version(event, libmyo_version_major), 117 | libmyo_event_get_firmware_version(event, libmyo_version_minor), 118 | libmyo_event_get_firmware_version(event, libmyo_version_patch), 119 | libmyo_event_get_firmware_version(event, libmyo_version_hardware_rev)}; 120 | listener->onPair(myo, time, version); 121 | break; 122 | } 123 | case libmyo_event_connected: { 124 | FirmwareVersion version = {libmyo_event_get_firmware_version(event, libmyo_version_major), 125 | libmyo_event_get_firmware_version(event, libmyo_version_minor), 126 | libmyo_event_get_firmware_version(event, libmyo_version_patch), 127 | libmyo_event_get_firmware_version(event, libmyo_version_hardware_rev)}; 128 | listener->onConnect(myo, time, version); 129 | break; 130 | } 131 | case libmyo_event_disconnected: 132 | listener->onDisconnect(myo, time); 133 | break; 134 | case libmyo_event_arm_recognized: 135 | listener->onArmRecognized(myo, time, 136 | static_cast(libmyo_event_get_arm(event)), 137 | static_cast(libmyo_event_get_x_direction(event))); 138 | break; 139 | case libmyo_event_arm_lost: 140 | listener->onArmLost(myo, time); 141 | break; 142 | case libmyo_event_orientation: 143 | listener->onOrientationData(myo, time, 144 | Quaternion(libmyo_event_get_orientation(event, libmyo_orientation_x), 145 | libmyo_event_get_orientation(event, libmyo_orientation_y), 146 | libmyo_event_get_orientation(event, libmyo_orientation_z), 147 | libmyo_event_get_orientation(event, libmyo_orientation_w))); 148 | listener->onAccelerometerData(myo, time, 149 | Vector3(libmyo_event_get_accelerometer(event, 0), 150 | libmyo_event_get_accelerometer(event, 1), 151 | libmyo_event_get_accelerometer(event, 2))); 152 | 153 | listener->onGyroscopeData(myo, time, 154 | Vector3(libmyo_event_get_gyroscope(event, 0), 155 | libmyo_event_get_gyroscope(event, 1), 156 | libmyo_event_get_gyroscope(event, 2))); 157 | 158 | break; 159 | case libmyo_event_pose: 160 | listener->onPose(myo, time, Pose(static_cast(libmyo_event_get_pose(event)))); 161 | break; 162 | case libmyo_event_rssi: 163 | listener->onRssi(myo, time, libmyo_event_get_rssi(event)); 164 | break; 165 | } 166 | } 167 | } 168 | 169 | inline 170 | void Hub::run(unsigned int duration_ms) 171 | { 172 | struct local { 173 | static libmyo_handler_result_t handler(void* user_data, libmyo_event_t event) { 174 | Hub* hub = static_cast(user_data); 175 | 176 | hub->onDeviceEvent(event); 177 | 178 | return libmyo_handler_continue; 179 | } 180 | }; 181 | libmyo_run(_hub, duration_ms, &local::handler, this, ThrowOnError()); 182 | } 183 | 184 | inline 185 | void Hub::runOnce(unsigned int duration_ms) 186 | { 187 | struct local { 188 | static libmyo_handler_result_t handler(void* user_data, libmyo_event_t event) { 189 | Hub* hub = static_cast(user_data); 190 | 191 | hub->onDeviceEvent(event); 192 | 193 | return libmyo_handler_stop; 194 | } 195 | }; 196 | libmyo_run(_hub, duration_ms, &local::handler, this, ThrowOnError()); 197 | } 198 | 199 | inline 200 | libmyo_hub_t Hub::libmyoObject() 201 | { 202 | return _hub; 203 | } 204 | 205 | inline 206 | Myo* Hub::lookupMyo(libmyo_myo_t opaqueMyo) const 207 | { 208 | Myo* myo = 0; 209 | for (std::vector::const_iterator I = _myos.begin(), IE = _myos.end(); I != IE; ++I) { 210 | if ((*I)->libmyoObject() == opaqueMyo) { 211 | myo = *I; 212 | break; 213 | } 214 | } 215 | 216 | return myo; 217 | } 218 | 219 | inline 220 | Myo* Hub::addMyo(libmyo_myo_t opaqueMyo) 221 | { 222 | Myo* myo = new Myo(opaqueMyo); 223 | 224 | _myos.push_back(myo); 225 | 226 | return myo; 227 | } 228 | 229 | } // namespace myo 230 | -------------------------------------------------------------------------------- /myo/cxx/impl/Myo_impl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #include "../Myo.hpp" 4 | #include "../detail/ThrowOnError.hpp" 5 | 6 | #include 7 | 8 | namespace myo { 9 | 10 | inline 11 | void Myo::vibrate(VibrationType type) 12 | { 13 | libmyo_vibrate(_myo, static_cast(type), ThrowOnError()); 14 | } 15 | 16 | inline 17 | void Myo::requestRssi() const 18 | { 19 | libmyo_request_rssi(_myo, ThrowOnError()); 20 | } 21 | 22 | inline 23 | libmyo_myo_t Myo::libmyoObject() const 24 | { 25 | return _myo; 26 | } 27 | 28 | inline 29 | Myo::Myo(libmyo_myo_t myo) 30 | : _myo(myo) 31 | { 32 | if (!_myo) { 33 | throw std::invalid_argument("Cannot construct Myo instance with null pointer"); 34 | } 35 | } 36 | 37 | inline 38 | Myo::~Myo() 39 | { 40 | } 41 | 42 | } // namespace myo 43 | -------------------------------------------------------------------------------- /myo/cxx/impl/Pose_impl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_CXX_IMPL_POSE_IMPL_HPP 4 | #define MYO_CXX_IMPL_POSE_IMPL_HPP 5 | 6 | #include "../Pose.hpp" 7 | 8 | #include 9 | 10 | namespace myo { 11 | 12 | inline 13 | Pose::Pose() 14 | : _type(unknown) 15 | { 16 | } 17 | 18 | inline 19 | Pose::Pose(Pose::Type type) 20 | : _type(type) 21 | { 22 | } 23 | 24 | inline 25 | bool Pose::operator==(Pose other) const 26 | { 27 | return _type == other._type; 28 | } 29 | 30 | inline 31 | bool Pose::operator!=(Pose other) const 32 | { 33 | return !(*this == other); 34 | } 35 | 36 | inline 37 | Pose::Type Pose::type() const 38 | { 39 | return _type; 40 | } 41 | 42 | inline 43 | bool operator==(Pose pose, Pose::Type type) 44 | { 45 | return pose.type() == type; 46 | } 47 | 48 | inline 49 | bool operator==(Pose::Type type, Pose pose) 50 | { 51 | return pose == type; 52 | } 53 | 54 | inline 55 | bool operator!=(Pose pose, Pose::Type type) 56 | { 57 | return !(pose == type); 58 | } 59 | 60 | inline 61 | bool operator!=(Pose::Type type, Pose pose) 62 | { 63 | return !(type == pose); 64 | } 65 | 66 | inline 67 | std::string Pose::toString() const 68 | { 69 | switch (type()) { 70 | case Pose::rest: 71 | return "rest"; 72 | case Pose::fist: 73 | return "fist"; 74 | case Pose::waveIn: 75 | return "waveIn"; 76 | case Pose::waveOut: 77 | return "waveOut"; 78 | case Pose::fingersSpread: 79 | return "fingersSpread"; 80 | case Pose::reserved1: 81 | return "reserved1"; 82 | case Pose::thumbToPinky: 83 | return "thumbToPinky"; 84 | case Pose::unknown: 85 | return "unknown"; 86 | } 87 | 88 | return ""; 89 | } 90 | 91 | inline 92 | std::ostream& operator<<(std::ostream& out, const Pose& pose) 93 | { 94 | return out << pose.toString(); 95 | } 96 | 97 | } // namespace myo 98 | 99 | #endif // MYO_CXX_IMPL_POSE_IMPL_HPP 100 | -------------------------------------------------------------------------------- /myo/libmyo.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_LIBMYO_H 4 | #define MYO_LIBMYO_H 5 | 6 | #include 7 | 8 | #include "libmyo/detail/visibility.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /// @file libmyo.h 15 | /// libmyo C API declarations. 16 | 17 | typedef void* libmyo_hub_t; 18 | 19 | /// \defgroup errors Error Handling 20 | /// @{ 21 | 22 | /// Function result codes. 23 | /// All libmyo functions that can fail return a value of this type. 24 | typedef enum { 25 | libmyo_success, 26 | libmyo_error, 27 | libmyo_error_invalid_argument, 28 | libmyo_error_runtime 29 | } libmyo_result_t; 30 | 31 | /// Opaque handle to detailed error information. 32 | typedef void* libmyo_error_details_t; 33 | 34 | /// Return a null-terminated string with a detailed error message. 35 | LIBMYO_EXPORT 36 | const char* libmyo_error_cstring(libmyo_error_details_t); 37 | 38 | /// Returns the kind of error that occurred. 39 | LIBMYO_EXPORT 40 | libmyo_result_t libmyo_error_kind(libmyo_error_details_t); 41 | 42 | /// Free the resources allocated by an error object. 43 | LIBMYO_EXPORT 44 | void libmyo_free_error_details(libmyo_error_details_t); 45 | 46 | /// @} 47 | 48 | /// @defgroup libmyo_hub Hub instance 49 | /// @{ 50 | 51 | /// Initialize a connection to the hub. 52 | /// \a application_identifier must follow a reverse domain name format (ex. com.domainname.appname). Application 53 | /// identifiers can be formed from the set of alphanumeric ASCII characters (a-z, A-Z, 0-9). The hyphen (-) and 54 | /// underscore (_) characters are permitted if they are not adjacent to a period (.) character (i.e. not at the start or 55 | /// end of each segment), but are not permitted in the top-level domain. Application identifiers must have three or more 56 | /// segments. For example, if a company's domain is example.com and the application is named hello-world, one could use 57 | /// "com.example.hello-world" as a valid application identifier. \a application_identifier can be NULL or empty. 58 | /// @returns libmyo_success if the connection is successfully established, otherwise: 59 | /// - libmyo_error_runtime if a connection could not be established 60 | /// - libmyo_error_invalid_argument if \a out_hub is NULL 61 | /// - libmyo_error_invalid_argument if \a application_identifier is longer than 255 characters 62 | /// - libmyo_error_invalid_argument if \a application_identifier is not in the proper reverse domain name format 63 | LIBMYO_EXPORT 64 | libmyo_result_t libmyo_init_hub(libmyo_hub_t* out_hub, const char* application_identifier, 65 | libmyo_error_details_t* out_error); 66 | 67 | /// Free the resources allocated to a hub. 68 | /// @returns libmyo_success if shutdown is successful, otherwise: 69 | /// - libmyo_error_invalid_argument if \a hub is NULL 70 | /// - libmyo_error if \a hub is not a valid \a hub 71 | LIBMYO_EXPORT 72 | libmyo_result_t libmyo_shutdown_hub(libmyo_hub_t hub, libmyo_error_details_t* out_error); 73 | 74 | /// @} 75 | 76 | /// @defgroup libmyo_myo Myo instances 77 | /// @{ 78 | 79 | /// Opaque type corresponding to a known Myo device. 80 | typedef void* libmyo_myo_t; 81 | 82 | /// Types of vibration 83 | typedef enum { 84 | libmyo_vibration_short, 85 | libmyo_vibration_medium, 86 | libmyo_vibration_long 87 | } libmyo_vibration_type_t; 88 | 89 | /// Vibrate the given myo. 90 | /// Can be called when a Myo is paired. 91 | /// @returns libmyo_success if the Myo successfully vibrated, otherwise 92 | /// - libmyo_error_invalid_argument if \a myo is NULL 93 | LIBMYO_EXPORT 94 | libmyo_result_t libmyo_vibrate(libmyo_myo_t myo, libmyo_vibration_type_t type, libmyo_error_details_t* out_error); 95 | 96 | /// Request the RSSI for a given myo. 97 | /// Can be called when a Myo is paired. A libmyo_event_rssi event will likely be generated with the value of the RSSI. 98 | /// @returns libmyo_success if the Myo successfully got the RSSI, otherwise 99 | /// - libmyo_error_invalid_argument if \a myo is NULL 100 | LIBMYO_EXPORT 101 | libmyo_result_t libmyo_request_rssi(libmyo_myo_t myo, libmyo_error_details_t* out_error); 102 | 103 | /// @} 104 | 105 | /// @defgroup libmyo_poses Pose recognition. 106 | /// @{ 107 | 108 | /// Supported poses. 109 | typedef enum { 110 | libmyo_pose_rest = 0, ///< Rest pose. 111 | libmyo_pose_fist = 1, ///< User is making a fist. 112 | libmyo_pose_wave_in = 2, ///< User has an open palm rotated towards the posterior of their wrist. 113 | libmyo_pose_wave_out = 3, ///< User has an open palm rotated towards the anterior of their wrist. 114 | libmyo_pose_fingers_spread = 4, ///< User has an open palm with their fingers spread away from each other. 115 | libmyo_pose_reserved1 = 5, ///< Reserved value; not a valid pose. 116 | libmyo_pose_thumb_to_pinky = 6, ///< User is touching the tip of their thumb to the tip of their pinky. 117 | 118 | libmyo_num_poses, ///< Number of poses supported; not a valid pose. 119 | 120 | libmyo_pose_unknown = 0xffff ///< Unknown pose. 121 | } libmyo_pose_t; 122 | 123 | static const libmyo_pose_t libmyo_trained_poses[] = { libmyo_pose_rest, libmyo_pose_fist, libmyo_pose_wave_in, 124 | libmyo_pose_wave_out, libmyo_pose_fingers_spread, 125 | libmyo_pose_thumb_to_pinky }; 126 | static const unsigned int libmyo_num_trained_poses = sizeof(libmyo_trained_poses) / sizeof(libmyo_trained_poses[0]); 127 | 128 | /// @} 129 | 130 | /// @defgroup libmyo_events Event Handling 131 | /// @{ 132 | 133 | /// Types of events. 134 | typedef enum { 135 | libmyo_event_paired, ///< Successfully paired with a Myo. 136 | libmyo_event_connected, ///< A Myo has successfully connected. 137 | libmyo_event_disconnected, ///< A Myo has been disconnected. 138 | libmyo_event_arm_recognized, ///< A Myo has recognized that it is now on an arm. 139 | libmyo_event_arm_lost, ///< A Myo has been moved or removed from the arm. 140 | libmyo_event_orientation, ///< Orientation data has been received. 141 | libmyo_event_pose, ///< A change in pose has been detected. @see libmyo_pose_t. 142 | libmyo_event_rssi, ///< An RSSI value has been received. 143 | } libmyo_event_type_t; 144 | 145 | /// Information about an event. 146 | typedef const void* libmyo_event_t; 147 | 148 | /// Retrieve the type of an event. 149 | LIBMYO_EXPORT 150 | uint32_t libmyo_event_get_type(libmyo_event_t event); 151 | 152 | /// Retrieve the timestamp of an event. 153 | /// @see libmyo_now() for details on timestamps. 154 | LIBMYO_EXPORT 155 | uint64_t libmyo_event_get_timestamp(libmyo_event_t event); 156 | 157 | /// Retrieve the Myo associated with an event. 158 | LIBMYO_EXPORT 159 | libmyo_myo_t libmyo_event_get_myo(libmyo_event_t event); 160 | 161 | /// Components of version. 162 | typedef enum { 163 | libmyo_version_major, ///< Major version. 164 | libmyo_version_minor, ///< Minor version. 165 | libmyo_version_patch, ///< Patch version. 166 | libmyo_version_hardware_rev, ///< Hardware revision. 167 | } libmyo_version_component_t; 168 | 169 | /// Retrieve the Myo armband's firmware version from this event. 170 | /// Valid for libmyo_event_paired and libmyo_event_connected events. 171 | LIBMYO_EXPORT 172 | unsigned int libmyo_event_get_firmware_version(libmyo_event_t event, libmyo_version_component_t); 173 | 174 | /// Enumeration identifying a right arm or left arm. @see libmyo_event_get_arm(). 175 | typedef enum { 176 | libmyo_arm_right, ///< Myo is on the right arm. 177 | libmyo_arm_left, ///< Myo is on the left arm. 178 | libmyo_arm_unknown, ///< Unknown arm. 179 | } libmyo_arm_t; 180 | 181 | /// Retrieve the arm associated with an event. 182 | /// Valid for libmyo_event_arm_recognized events only. 183 | LIBMYO_EXPORT 184 | libmyo_arm_t libmyo_event_get_arm(libmyo_event_t event); 185 | 186 | /// Possible directions for Myo's +x axis relative to a user's arm. 187 | typedef enum { 188 | libmyo_x_direction_toward_wrist, ///< Myo's +x axis is pointing toward the user's wrist. 189 | libmyo_x_direction_toward_elbow, ///< Myo's +x axis is pointing toward the user's elbow. 190 | libmyo_x_direction_unknown, ///< Unknown +x axis direction. 191 | } libmyo_x_direction_t; 192 | 193 | /// Retrieve the x-direction associated with an event. 194 | /// The x-direction specifies which way Myo's +x axis is pointing relative to the user's arm. 195 | /// Valid for libmyo_event_arm_recognized events only. 196 | LIBMYO_EXPORT 197 | libmyo_x_direction_t libmyo_event_get_x_direction(libmyo_event_t event); 198 | 199 | /// Index into orientation data, which is provided as a quaternion. 200 | /// Orientation data is returned as a unit quaternion of floats, represented as `w + x * i + y * j + z * k`. 201 | typedef enum { 202 | libmyo_orientation_x = 0, ///< First component of the quaternion's vector part 203 | libmyo_orientation_y = 1, ///< Second component of the quaternion's vector part 204 | libmyo_orientation_z = 2, ///< Third component of the quaternion's vector part 205 | libmyo_orientation_w = 3, ///< Scalar component of the quaternion. 206 | } libmyo_orientation_index; 207 | 208 | /// Retrieve orientation data associated with an event. 209 | /// Valid for libmyo_event_orientation events only. 210 | /// @see libmyo_orientation_index 211 | LIBMYO_EXPORT 212 | float libmyo_event_get_orientation(libmyo_event_t event, libmyo_orientation_index index); 213 | 214 | /// Retrieve raw accelerometer data associated with an event in units of g. 215 | /// Valid for libmyo_event_orientation events only. 216 | /// Requires `index < 3`. 217 | LIBMYO_EXPORT 218 | float libmyo_event_get_accelerometer(libmyo_event_t event, unsigned int index); 219 | 220 | /// Retrieve raw gyroscope data associated with an event in units of deg/s. 221 | /// Valid for libmyo_event_orientation events only. 222 | /// Requires `index < 3`. 223 | LIBMYO_EXPORT 224 | float libmyo_event_get_gyroscope(libmyo_event_t event, unsigned int index); 225 | 226 | /// Retrieve the pose associated with an event. 227 | /// Valid for libmyo_event_pose events only. 228 | LIBMYO_EXPORT 229 | libmyo_pose_t libmyo_event_get_pose(libmyo_event_t event); 230 | 231 | /// Retreive the RSSI associated with an event. 232 | /// Valid for libmyo_event_rssi events only. 233 | LIBMYO_EXPORT 234 | int8_t libmyo_event_get_rssi(libmyo_event_t event); 235 | 236 | /// Return type for event handlers. 237 | typedef enum { 238 | libmyo_handler_continue, ///< Continue processing events 239 | libmyo_handler_stop, ///< Stop processing events 240 | } libmyo_handler_result_t; 241 | 242 | /// Callback function type to handle events as they occur from libmyo_run(). 243 | typedef libmyo_handler_result_t (*libmyo_handler_t)(void* user_data, libmyo_event_t event); 244 | 245 | /// Process events and call the provided callback as they occur. 246 | /// Runs for up to approximately \a duration_ms milliseconds or until a called handler returns libmyo_handler_stop. 247 | /// @returns libmyo_success after a successful run, otherwise 248 | /// - libmyo_error_invalid_argument if \a hub is NULL 249 | /// - libmyo_error_invalid_argument if \a handler is NULL 250 | LIBMYO_EXPORT 251 | libmyo_result_t libmyo_run(libmyo_hub_t hub, unsigned int duration_ms, libmyo_handler_t handler, void* user_data, 252 | libmyo_error_details_t* out_error); 253 | 254 | /// @} 255 | 256 | #ifdef __cplusplus 257 | } // extern "C" 258 | #endif 259 | 260 | #endif // MYO_LIBMYO_H 261 | -------------------------------------------------------------------------------- /myo/libmyo/detail/visibility.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_LIBMYO_DETAIL_VISIBILITY_H 4 | #define MYO_LIBMYO_DETAIL_VISIBILITY_H 5 | 6 | #if defined(_WIN32) || defined(__CYGWIN__) 7 | #ifdef myo_EXPORTS 8 | #ifdef __GNUC__ 9 | #define LIBMYO_EXPORT __attribute__ ((dllexport)) 10 | #else 11 | #define LIBMYO_EXPORT __declspec(dllexport) 12 | #endif 13 | #else 14 | #ifdef LIBMYO_STATIC_BUILD 15 | #define LIBMYO_EXPORT 16 | #else 17 | #ifdef __GNUC__ 18 | #define LIBMYO_EXPORT __attribute__ ((dllimport)) 19 | #else 20 | #define LIBMYO_EXPORT __declspec(dllimport) 21 | #endif 22 | #endif 23 | #endif 24 | #else 25 | #if __GNUC__ >= 4 26 | #define LIBMYO_EXPORT __attribute__ ((visibility ("default"))) 27 | #else 28 | #define LIBMYO_EXPORT 29 | #endif 30 | #endif 31 | 32 | #endif // MYO_LIBMYO_DETAIL_VISIBILITY_H 33 | -------------------------------------------------------------------------------- /myo/myo.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2014 Thalmic Labs Inc. 2 | // Distributed under the Myo SDK license agreement. See LICENSE.txt for details. 3 | #ifndef MYO_MYO_HPP 4 | #define MYO_MYO_HPP 5 | 6 | /// The namespace in which all of the %Myo C++ bindings are contained. 7 | namespace myo {} 8 | 9 | #include "cxx/DeviceListener.hpp" 10 | #include "cxx/Hub.hpp" 11 | #include "cxx/Myo.hpp" 12 | #include "cxx/Pose.hpp" 13 | #include "cxx/Quaternion.hpp" 14 | #include "cxx/Vector3.hpp" 15 | 16 | #endif // MYO_MYO_HPP 17 | -------------------------------------------------------------------------------- /myo32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/myo32.dll -------------------------------------------------------------------------------- /myo64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartin015/MYO-python/cbbbeba94ba516f7661bcffec35e777b7d0b6e8f/myo64.dll --------------------------------------------------------------------------------