├── .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
--------------------------------------------------------------------------------