Myo Scol plugin
sMyo.cpp
1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OpenSpace3D
4 For the latest info, see http://www.openspace3d.com
5 
6 Copyright (c) 2013 I-maginer
7 
8 This program is free software; you can redistribute it and/or modify it under
9 the terms of the GNU Lesser General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
12 
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20 http://www.gnu.org/copyleft/lesser.txt
21 
22 -----------------------------------------------------------------------------
23 */
24 
25 #include "SMyo.h"
26 
27 extern int MYO_CONNECTED_CB;
28 extern int MYO_DISCONNECTED_CB;
29 extern int MYO_ORIENTATION_CB;
30 extern int MYO_ACCEL_CB;
31 extern int MYO_POSE_CB;
32 extern int MYO_ARMRECOGNIZED_CB;
33 extern int MYO_ARMLOST_CB;
34 
35 // Initialize singleton
36 SMyoManager* SMyoManager::_singleton = 0;
37 
43 {
44  mMyoInstance = 0;
45  mDirection = xDirectionUnknown;
46  mConnected = false;
47  mPrevQuat = myo::Quaternion<float>(0.0f, 0.0f, 0.0f, 1.0f);
48 }
49 
51 {
52  Disconnect();
53  // mMyoAvailable
54 }
55 
56 myo::Myo* SMyo::GetMyoInstance()
57 {
58  return mMyoInstance;
59 }
60 
61 void SMyo::SetMyoInstance(myo::Myo* myoInstance)
62 {
63  mMyoInstance = myoInstance;
64 }
65 
66 void SMyo::SetDirection(XDirection direction)
67 {
68  mDirection = direction;
69 }
70 
71 XDirection SMyo::GetDirection()
72 {
73  return mDirection;
74 }
75 
76 void SMyo::Connect()
77 {
78  mConnected = true;
79  OBJpostEvent(MYO_CONNECTED_CB, SCOL_PTR this, 0);
80 }
81 
82 void SMyo::Disconnect()
83 {
84  mConnected = false;
85  OBJpostEvent(MYO_DISCONNECTED_CB, SCOL_PTR this, 0);
86 }
87 
88 void SMyo::SendPose(myo::Pose pose)
89 {
90  SCbData* data = new SCbData();
91  data->pose = pose;
92  OBJpostEvent(MYO_POSE_CB, SCOL_PTR this, (int)data);
93 }
94 
95 void SMyo::SendOrientation(myo::Quaternion<float> quat)
96 {
97  SCbData* data = new SCbData();
98  quat = quat.normalized();
99  myo::Quaternion<float> dir = Quaternion<float>(0.0f, 1.0f, 0.0f, 0.0f);
100  quat = (mDirection != xDirectionTowardWrist) ? Quaternion<float>(quat.y(), quat.z(), quat.x(), quat.w()) : Quaternion<float>(quat.y(), quat.z(), quat.x(), quat.w());
101  data->quat = quat * dir;
102  mPrevQuat = quat;
103  OBJpostEvent(MYO_ORIENTATION_CB, SCOL_PTR this, (int)data);
104 }
105 
106 void SMyo::SendAccel(myo::Vector3<float> vec)
107 {
108  SCbData* data = new SCbData();
109  data->svec = vec;
110 
111  OBJpostEvent(MYO_ACCEL_CB, SCOL_PTR this, (int)data);
112 }
113 
114 void SMyo::Vibrate(myo::Myo::VibrationType type)
115 {
116  if (mMyoInstance)
117  mMyoInstance->vibrate(type);
118 }
119 
124 SMyoManager::SMyoManager()
125 {
126  mMyoHub = 0;
127  mTerminate = false;
128 }
129 
130 SMyoManager::~SMyoManager()
131 {
132  mTerminate = true;
133  mThread.join();
134 
135  MyoList::iterator ismyo;
136  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
137  {
138  SMyo* myoInstance = (*ismyo);
139  SAFE_DELETE(myoInstance);
140  ismyo = mMyoList.erase(ismyo);
141  }
142 
143  SAFE_DELETE(mMyoHub);
144 }
145 
146 SMyoManager* SMyoManager::GetInstance()
147 {
148  if (0 == _singleton)
149  {
150  _singleton = new SMyoManager();
151  }
152 
153  return _singleton;
154 }
155 
156 void SMyoManager::Kill()
157 {
158  if (0 != _singleton)
159  {
160  delete _singleton;
161  _singleton = 0;
162  }
163 }
164 
165 SMyo* SMyoManager::AddMyoInstance()
166 {
167  boost::upgrade_lock< boost::shared_mutex > lock(mMutex);
168  if (mMyoHub == 0)
169  {
170  try
171  {
172  mMyoHub = new myo::Hub("com.scol.myo");
173  if (mMyoHub)
174  {
175  mMyoHub->setLockingPolicy(Hub::lockingPolicyNone);
176  mMyoHub->addListener(this);
177 
178  mTerminate = false;
179  mThread = boost::thread(boost::bind(&SMyoManager::UpdateThread, this));
180  }
181  }
182  catch(std::exception &e)
183  {
184  //dongle not connected or already used
185  MMechostr(MSKRUNTIME, "Myo error : %s", e.what());
186  }
187  }
188 
189  SMyo* myoInstance = 0;
190 
191  if (mMyoHub)
192  {
193  //take the lock exclusive
194  boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
195 
196  myoInstance = new SMyo();
197  mMyoList.insert(myoInstance);
198  }
199 
200  return myoInstance;
201 }
202 
203 void SMyoManager::RemoveMyoInstance(SMyo* myoInstance)
204 {
205  {
206  boost::upgrade_lock< boost::shared_mutex > lock(mMutex);
207 
208  if (myoInstance->GetMyoInstance())
209  {
210  //take the lock exclusive
211  boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
212  mMyoAvailable.insert(myoInstance->GetMyoInstance());
213  }
214 
215  MyoList::iterator ismyo = mMyoList.find(myoInstance);
216  if (ismyo != mMyoList.end())
217  {
218  //take the lock exclusive
219  boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
220 
221  mMyoList.erase(ismyo);
222  SAFE_DELETE(myoInstance);
223  }
224  }
225 
226  if (mMyoList.empty() && mMyoHub != 0)
227  {
228  //Remove thread
229  mTerminate = true;
230  mThread.join();
231 
232  mMyoHub->removeListener(this);
233  mMyoHub->runOnce(1);
234  SAFE_DELETE(mMyoHub);
235  mMyoAvailable.clear();
236  }
237 }
238 
239 void SMyoManager::UpdateThread()
240 {
241  while (!mTerminate)
242  {
243  if (!mTerminate)
244  boost::shared_lock< boost::shared_mutex > lock(mMutex);
245 
246  // get number of paired myo
247  size_t nbPaired = 0;
248  MyoList::iterator ismyo;
249 
250  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
251  {
252  SMyo* myoInstance = (*ismyo);
253  if (myoInstance->GetMyoInstance() == 0)
254  {
255  if (mMyoAvailable.size() > 0)
256  {
257  myo::Myo* myo = (*mMyoAvailable.begin());
258  myoInstance->SetMyoInstance(myo);
259  myoInstance->Connect();
260  mMyoAvailable.erase(mMyoAvailable.begin());
261  nbPaired++;
262  }
263  }
264  else
265  {
266  nbPaired++;
267  }
268  }
269 
270  // need to pair myos
271  if (nbPaired < mMyoList.size())
272  {
273  myo::Myo* myo = 0;
274  try
275  {
276  myo = mMyoHub->waitForMyo(1);
277  }
278  catch (std::exception &e)
279  {
280  std::string mess = e.what();
281  MMechostr(MSKDEBUG, "Myo Exception : %s", e.what());
282  //error
283  }
284  }
285 
286  mMyoHub->run(33);
287  }
288 }
289 
290 void SMyoManager::onPair(Myo *myo, uint64_t timestamp, FirmwareVersion firmwareVersion)
291 {
292  //all myo listener callbacks are in a foreign thread
293  //boost::mutex::scoped_lock l(mMutex);
294 }
295 
296 void SMyoManager::onConnect(Myo *myo, uint64_t timestamp, FirmwareVersion firmwareVersion)
297 {
298  //all myo listener callbacks are in a foreign thread
299  //boost::mutex::scoped_lock l(mMutex);
300  mMyoAvailable.insert(myo);
301 
302  MyoList::iterator ismyo;
303  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
304  {
305  SMyo* myoInstance = (*ismyo);
306  if (myoInstance->GetMyoInstance() == 0)
307  {
308  myoInstance->SetMyoInstance(myo);
309  myoInstance->Connect();
310 
311  MyoAvailables::iterator availableIt = mMyoAvailable.find(myo);
312  if (availableIt != mMyoAvailable.end())
313  mMyoAvailable.erase(availableIt);
314  break;
315  }
316  }
317 }
318 
319 void SMyoManager::onDisconnect(Myo *myo, uint64_t timestamp)
320 {
321  //all myo listener callbacks are in a foreign thread
322  //boost::mutex::scoped_lock l(mMutex);
323  MyoAvailables::iterator availableIt = mMyoAvailable.find(myo);
324  if (availableIt != mMyoAvailable.end())
325  mMyoAvailable.erase(availableIt);
326 
327  MyoList::iterator ismyo;
328  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
329  {
330  SMyo* myoInstance = (*ismyo);
331  if (myoInstance->GetMyoInstance() == myo)
332  {
333  myoInstance->SetMyoInstance(0);
334  myoInstance->Disconnect();
335  break;
336  }
337  }
338 }
339 
340 void SMyoManager::onPose(Myo *myo, uint64_t timestamp, Pose pose)
341 {
342  //all myo listener callbacks are in a foreign thread
343  //boost::mutex::scoped_lock l(mMutex);
344 
345  MyoList::iterator ismyo;
346  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
347  {
348  SMyo* myoInstance = (*ismyo);
349  if (myoInstance->GetMyoInstance() == myo)
350  {
351  myoInstance->SendPose(pose);
352  break;
353  }
354  }
355 }
356 
357 void SMyoManager::onOrientationData(Myo *myo, uint64_t timestamp, const Quaternion< float > &rotation)
358 {
359  //all myo listener callbacks are in a foreign thread
360  //boost::mutex::scoped_lock l(mMutex);
361 
362  MyoList::iterator ismyo;
363  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
364  {
365  SMyo* myoInstance = (*ismyo);
366  if (myoInstance->GetMyoInstance() == myo)
367  {
368  myoInstance->SendOrientation(rotation);
369  break;
370  }
371  }
372 }
373 
374 void SMyoManager::onAccelerometerData(Myo *myo, uint64_t timestamp, const Vector3< float > &accel)
375 {
376  //all myo listener callbacks are in a foreign thread
377  //boost::mutex::scoped_lock l(mMutex);
378 
379  MyoList::iterator ismyo;
380  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
381  {
382  SMyo* myoInstance = (*ismyo);
383  if (myoInstance->GetMyoInstance() == myo)
384  {
385  myoInstance->SendAccel(accel);
386  break;
387  }
388  }
389 }
390 
391 void SMyoManager::onGyroscopeData(Myo *myo, uint64_t timestamp, const Vector3< float > &gyro)
392 {
393  //all myo listener callbacks are in a foreign thread
394  //boost::mutex::scoped_lock l(mMutex);
395 }
396 
397 void SMyoManager::onRssi(Myo *myo, uint64_t timestamp, int8_t rssi)
398 {
399  //all myo listener callbacks are in a foreign thread
400  //boost::mutex::scoped_lock l(mMutex);
401 }
402 
403 void SMyoManager::onArmSync(Myo* myo, uint64_t timestamp, Arm arm, XDirection xDirection)
404 {
405  //all myo listener callbacks are in a foreign thread
406  //boost::mutex::scoped_lock l(mMutex);
407 
408  MyoList::iterator ismyo;
409  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
410  {
411  SMyo* myoInstance = (*ismyo);
412  myoInstance->SetDirection(xDirection);
413  if (myoInstance->GetMyoInstance() == myo)
414  {
415  OBJpostEvent(MYO_ARMRECOGNIZED_CB, (int)myoInstance, (int)arm);
416  break;
417  }
418  }
419 }
420 
421 void SMyoManager::onArmUnsync(Myo* myo, uint64_t timestamp)
422 {
423  //all myo listener callbacks are in a foreign thread
424  //boost::mutex::scoped_lock l(mMutex);
425 
426  MyoList::iterator ismyo;
427  for (ismyo = mMyoList.begin(); ismyo != mMyoList.end(); ismyo++)
428  {
429  SMyo* myoInstance = (*ismyo);
430  if (myoInstance->GetMyoInstance() == myo)
431  {
432  OBJpostEvent(MYO_ARMLOST_CB, (int)myoInstance, 0);
433  break;
434  }
435  }
436 }
437 
438 void SMyoManager::onUnlock(Myo* myo, uint64_t timestamp)
439 {
440 }
441 
442 void SMyoManager::onLock(Myo* myo, uint64_t timestamp)
443 {
444 }
Definition: sMyo.h:63
~SMyo()
Definition: sMyo.cpp:50
SMyo()
Definition: sMyo.cpp:42
Definition: sMyo.h:40