PageRenderTime 28ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/vrpn_Tracker_ThalmicLabsMyo.C

https://gitlab.com/sat-metalab/vrpn
C | 246 lines | 182 code | 44 blank | 20 comment | 39 complexity | d6c379d0b2ceabb40da199b10962fe78 MD5 | raw file
  1. #include "vrpn_Tracker_ThalmicLabsMyo.h"
  2. #ifdef VRPN_INCLUDE_THALMICLABSMYO
  3. #include "vrpn_Connection.h" // for vrpn_CONNECTION_LOW_LATENCY, etc
  4. #include "quat.h"
  5. /*
  6. * TODO :
  7. * Use myo timestamp when possible
  8. * Timestamps are 64 bit unsigned integers that correspond to a number of microseconds since some (unspecified) period in time. Timestamps are monotonically non-decreasing.
  9. * Stream raw emg data ?
  10. */
  11. // --------------------------------------------------------------------------
  12. // Constructor:
  13. // name (i): device name
  14. // c (i): vrp8n_Connection
  15. // useLock (b): require unlock gesture before detecting any gesture
  16. // armSide (ARMSIDE) : specify (or don't) the arm side for the myo
  17. vrpn_Tracker_ThalmicLabsMyo::vrpn_Tracker_ThalmicLabsMyo(const char *name, vrpn_Connection *c, bool useLock, ARMSIDE armSide) :
  18. vrpn_Tracker(name, c),
  19. vrpn_Analog(name, c),
  20. vrpn_Button_Filter(name, c),
  21. _armSide(armSide),
  22. hub(NULL),
  23. _myo(NULL),
  24. _analogChanged(false)
  25. {
  26. while (hub == NULL)
  27. {
  28. try
  29. {
  30. hub = new myo::Hub();
  31. hub->setLockingPolicy(useLock ? myo::Hub::lockingPolicyStandard : myo::Hub::lockingPolicyNone);
  32. hub->addListener(this);
  33. /// Set up sensor counts
  34. vrpn_Analog::num_channel = 9; // 0,1,2 : euler rotation - 3,4,5 : acceleration - 6,7,8 : gyroscope
  35. vrpn_Button::num_buttons = libmyo_num_poses + 1; // we add one for lock/unlock
  36. vrpn_Tracker::num_sensors = 1; // we have orientation and acceleration for the tracker
  37. vrpn_gettimeofday(&_timestamp, NULL);
  38. }
  39. catch (const std::exception& e) {
  40. std::cerr << "Error: " << e.what() << std::endl;
  41. }
  42. }
  43. }
  44. vrpn_Tracker_ThalmicLabsMyo::~vrpn_Tracker_ThalmicLabsMyo()
  45. {
  46. if (hub != NULL)
  47. delete hub;
  48. }
  49. void vrpn_Tracker_ThalmicLabsMyo::mainloop() {
  50. if (hub == NULL)
  51. return;
  52. // server update. We only need to call this once for all three
  53. // base devices because it is in the unique base class.
  54. server_mainloop();
  55. hub->runOnce(1);
  56. // only report once per loop for analog changes
  57. if (_analogChanged)
  58. {
  59. vrpn_Analog::report_changes(vrpn_CONNECTION_LOW_LATENCY);
  60. _analogChanged = false;
  61. }
  62. }
  63. void vrpn_Tracker_ThalmicLabsMyo::_report_lock() {
  64. vrpn_gettimeofday(&_timestamp, NULL);
  65. double dt = vrpn_TimevalDurationSeconds(_timestamp, vrpn_Button::timestamp);
  66. vrpn_Button::timestamp = _timestamp;
  67. buttons[0] = _locked;
  68. vrpn_Button::report_changes();
  69. }
  70. void vrpn_Tracker_ThalmicLabsMyo::onPair(myo::Myo* myo, uint64_t timestamp, myo::FirmwareVersion firmwareVersion)
  71. {
  72. std::cout << "Paired with Myo." << std::endl;
  73. myo->vibrate(myo->vibrationShort);
  74. }
  75. void vrpn_Tracker_ThalmicLabsMyo::onConnect(myo::Myo* myo, uint64_t timestamp, myo::FirmwareVersion firmwareVersion)
  76. {
  77. std::cout << "Myo Connected." << std::endl;
  78. myo->vibrate(myo->vibrationShort);
  79. }
  80. void vrpn_Tracker_ThalmicLabsMyo::onDisconnect(myo::Myo* myo, uint64_t timestamp)
  81. {
  82. std::cout << "Myo disconnected." << std::endl;
  83. if (myo == _myo)
  84. _myo = NULL;
  85. }
  86. void vrpn_Tracker_ThalmicLabsMyo::onPose(myo::Myo* myo, uint64_t timestamp, myo::Pose pose)
  87. {
  88. if (myo != _myo)
  89. return;
  90. vrpn_gettimeofday(&_timestamp, NULL);
  91. double dt = vrpn_TimevalDurationSeconds(_timestamp, vrpn_Button::timestamp);
  92. vrpn_Button::timestamp = _timestamp;
  93. // std::cout << "Myo switched to pose " << pose.toString() << "." << std::endl;
  94. buttons[0] = _locked;
  95. // reset all buttons to 0. Maybe we should only do this if rest is on ?
  96. for (int i = 1; i < libmyo_num_poses + 1; ++i)
  97. buttons[i] = 0;
  98. buttons[pose.type() + 1] = 1;
  99. vrpn_Button::report_changes();
  100. }
  101. void vrpn_Tracker_ThalmicLabsMyo::onArmSync(myo::Myo* myo, uint64_t timestamp, myo::Arm arm, myo::XDirection xDirection)
  102. {
  103. std::cout << "Myo on arm : " << (arm == myo::armLeft ? "Left." : "Right.") << std::endl;
  104. if (_armSide == ARMSIDE::ANY || (_armSide == ARMSIDE::RIGHT && arm == myo::armRight) || (_armSide == ARMSIDE::LEFT && arm == myo::armLeft))
  105. {
  106. std::cout << "Myo : " << d_servicename << " accepted" << std::endl;
  107. myo->vibrate(myo->vibrationShort);
  108. _myo = myo;
  109. }
  110. else
  111. {
  112. std::cout << "Myo : " << d_servicename << " NOT accepted : wrong arm detected" << std::endl;
  113. }
  114. }
  115. void vrpn_Tracker_ThalmicLabsMyo::onArmUnsync(myo::Myo* myo, uint64_t timestamp)
  116. {
  117. if (myo != _myo)
  118. return;
  119. std::cout << "Myo : " << d_servicename <<" removed from arm."<< std::endl;
  120. myo->vibrate(myo->vibrationLong);
  121. _myo = NULL;
  122. }
  123. void vrpn_Tracker_ThalmicLabsMyo::onUnlock(myo::Myo* myo, uint64_t timestamp)
  124. {
  125. if (myo != _myo)
  126. return;
  127. _locked = false;
  128. _report_lock();
  129. }
  130. void vrpn_Tracker_ThalmicLabsMyo::onLock(myo::Myo* myo, uint64_t timestamp)
  131. {
  132. if (myo != _myo)
  133. return;
  134. _locked = true;
  135. _report_lock();
  136. }
  137. void vrpn_Tracker_ThalmicLabsMyo::onOrientationData(myo::Myo* myo, uint64_t timestamp, const myo::Quaternion<float>& rotation)
  138. {
  139. if (myo != _myo)
  140. return;
  141. if (!d_connection) {
  142. return;
  143. }
  144. vrpn_gettimeofday(&_timestamp, NULL);
  145. double dt = vrpn_TimevalDurationSeconds(_timestamp, vrpn_Button::timestamp);
  146. vrpn_Tracker::timestamp = _timestamp;
  147. vrpn_Analog::timestamp = _timestamp;
  148. d_quat[0] = rotation.x();
  149. d_quat[1] = rotation.y();
  150. d_quat[2] = rotation.z();
  151. d_quat[3] = rotation.w();
  152. // do the same as analog, with euler angles (maybe offset from when OnArmSync?)
  153. q_vec_type euler;
  154. q_to_euler(euler, d_quat);
  155. channel[ANALOG_ROTATION_X] = euler[Q_ROLL];
  156. channel[ANALOG_ROTATION_Y] = euler[Q_PITCH];
  157. channel[ANALOG_ROTATION_Z] = euler[Q_YAW];
  158. char msgbuf[1000];
  159. int len = vrpn_Tracker::encode_to(msgbuf);
  160. if (d_connection->pack_message(len, _timestamp, position_m_id, d_sender_id, msgbuf, vrpn_CONNECTION_LOW_LATENCY)) {
  161. fprintf(stderr, "Thalmic Lab's myo tracker: can't write message: tossing\n");
  162. }
  163. _analogChanged = true;
  164. }
  165. void vrpn_Tracker_ThalmicLabsMyo::onAccelerometerData(myo::Myo* myo, uint64_t timestamp, const myo::Vector3<float>& accel)
  166. {
  167. if (myo != _myo)
  168. return;
  169. if (!d_connection) {
  170. return;
  171. }
  172. vrpn_gettimeofday(&_timestamp, NULL);
  173. double dt = vrpn_TimevalDurationSeconds(_timestamp, vrpn_Button::timestamp);
  174. vrpn_Tracker::timestamp = _timestamp;
  175. vrpn_Analog::timestamp = _timestamp;
  176. acc[0] = accel[0];
  177. acc[1] = accel[1];
  178. acc[2] = accel[2];
  179. // same for analog
  180. channel[ANALOG_ACCEL_X] = accel[0];
  181. channel[ANALOG_ACCEL_Y] = accel[1];
  182. channel[ANALOG_ACCEL_Z] = accel[2];
  183. char msgbuf[1000];
  184. int len = encode_acc_to(msgbuf);
  185. if (d_connection->pack_message(len, _timestamp, accel_m_id, d_sender_id, msgbuf, vrpn_CONNECTION_LOW_LATENCY)) {
  186. fprintf(stderr, "Thalmic Lab's myo tracker: can't write message: tossing\n");
  187. }
  188. _analogChanged = true;
  189. }
  190. void vrpn_Tracker_ThalmicLabsMyo::onGyroscopeData(myo::Myo* myo, uint64_t timestamp, const myo::Vector3<float>& gyro)
  191. {
  192. if (myo != _myo)
  193. return;
  194. vrpn_gettimeofday(&_timestamp, NULL);
  195. double dt = vrpn_TimevalDurationSeconds(_timestamp, vrpn_Button::timestamp);
  196. vrpn_Analog::timestamp = _timestamp;
  197. channel[ANALOG_GYRO_X] = gyro[0];
  198. channel[ANALOG_GYRO_Y] = gyro[1];
  199. channel[ANALOG_GYRO_Z] = gyro[2];
  200. _analogChanged = true;
  201. }
  202. #endif