Fawkes API  Fawkes Development Version
usertracker_thread.cpp
1 
2 /***************************************************************************
3  * usertracker_thread.cpp - OpenNI user tracker thread
4  *
5  * Created: Sun Feb 27 17:53:38 2011
6  * Copyright 2006-2011 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "usertracker_thread.h"
24 #include "utils/setup.h"
25 
26 #include <core/threading/mutex_locker.h>
27 #include <interfaces/HumanSkeletonInterface.h>
28 #include <interfaces/HumanSkeletonProjectionInterface.h>
29 #include <fvutils/ipc/shm_image.h>
30 
31 #include <memory>
32 
33 using namespace fawkes;
34 using namespace firevision;
35 
36 /** @class OpenNiUserTrackerThread "usertracker_thread.h"
37  * OpenNI User Tracker Thread.
38  * This thread requests a user tracker node from OpenNI and publishes the
39  * retrieved information via the blackboard.
40  *
41  * @author Tim Niemueller
42  */
43 
44 /** Constructor. */
46  : Thread("OpenNiUserTrackerThread", Thread::OPMODE_WAITFORWAKEUP),
47  BlockedTimingAspect(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_PROCESS)
48 {
49 }
50 
51 
52 /** Destructor. */
54 {
55 }
56 
57 
58 static void XN_CALLBACK_TYPE
59 cb_new_user(xn::UserGenerator &generator, XnUserID id, void *cookie)
60 {
61  OpenNiUserTrackerThread *t = static_cast<OpenNiUserTrackerThread *>(cookie);
62  t->new_user(id);
63 }
64 
65 static void XN_CALLBACK_TYPE
66 cb_lost_user(xn::UserGenerator &generator, XnUserID id, void *cookie)
67 {
68  OpenNiUserTrackerThread *t = static_cast<OpenNiUserTrackerThread *>(cookie);
69  t->lost_user(id);
70 }
71 
72 static void XN_CALLBACK_TYPE
73 cb_pose_start(xn::PoseDetectionCapability &capability,
74  const XnChar *pose_name, XnUserID id, void* cookie)
75 {
76  OpenNiUserTrackerThread *t = static_cast<OpenNiUserTrackerThread *>(cookie);
77  t->pose_start(id, pose_name);
78 }
79 
80 static void XN_CALLBACK_TYPE
81 cb_pose_end(xn::PoseDetectionCapability &capability,
82  const XnChar *pose_name, XnUserID id, void* cookie)
83 {
84  OpenNiUserTrackerThread *t = static_cast<OpenNiUserTrackerThread *>(cookie);
85  t->pose_end(id, pose_name);
86 }
87 
88 static void XN_CALLBACK_TYPE
89 cb_calibration_start(xn::SkeletonCapability &capability, XnUserID id, void *cookie)
90 {
91  OpenNiUserTrackerThread *t = static_cast<OpenNiUserTrackerThread *>(cookie);
92  t->calibration_start(id);
93 }
94 
95 #if XN_VERSION_GE(1,3,2,0)
96 static void XN_CALLBACK_TYPE
97 cb_calibration_complete(xn::SkeletonCapability &capability, XnUserID id,
98  XnCalibrationStatus status, void *cookie)
99 {
100  OpenNiUserTrackerThread *t = static_cast<OpenNiUserTrackerThread *>(cookie);
101  t->calibration_end(id, status == XN_CALIBRATION_STATUS_OK);
102 }
103 #else
104 static void XN_CALLBACK_TYPE
105 cb_calibration_end(xn::SkeletonCapability &capability, XnUserID id,
106  XnBool success, void *cookie)
107 {
108  OpenNiUserTrackerThread *t = static_cast<OpenNiUserTrackerThread *>(cookie);
109  t->calibration_end(id, success);
110 }
111 #endif
112 
113 
114 void
116 {
118 
119  __user_gen = new xn::UserGenerator();
120  std::auto_ptr<xn::UserGenerator> usergen_autoptr(__user_gen);
121 
122  __depth_gen = new xn::DepthGenerator();
123  std::auto_ptr<xn::DepthGenerator> depthgen_autoptr(__depth_gen);
124 
125  XnStatus st;
126 
127  fawkes::openni::find_or_create_node(openni, XN_NODE_TYPE_DEPTH, __depth_gen);
128  fawkes::openni::setup_map_generator(*__depth_gen, config);
129  fawkes::openni::find_or_create_node(openni, XN_NODE_TYPE_USER, __user_gen);
130 
131  if (!__user_gen->IsCapabilitySupported(XN_CAPABILITY_SKELETON)) {
132  throw Exception("User generator does not support skeleton capability");
133  }
134 
135  __scene_md = new xn::SceneMetaData();
136  std::auto_ptr<xn::SceneMetaData> scenemd_autoptr(__scene_md);
137  if ((st = __user_gen->GetUserPixels(0, *__scene_md)) != XN_STATUS_OK) {
138  throw Exception("Failed to get scene meta data (%s)", xnGetStatusString(st));
139  }
140 
141  st = __user_gen->RegisterUserCallbacks(cb_new_user, cb_lost_user,
142  this, __user_cb_handle);
143  if (st != XN_STATUS_OK) {
144  throw Exception("Failed to register user callbacks (%s)",
145  xnGetStatusString(st));
146  }
147 
148  __skelcap = new xn::SkeletonCapability(__user_gen->GetSkeletonCap());
149 
150 #if XN_VERSION_GE(1,3,2,0)
151  st = __skelcap->RegisterToCalibrationStart(cb_calibration_start,
152  this, __calib_start_cb_handle);
153  if (st != XN_STATUS_OK) {
154  throw Exception("Failed to register calibration start event (%s)",
155  xnGetStatusString(st));
156  }
157  st = __skelcap->RegisterToCalibrationComplete(cb_calibration_complete,
158  this, __calib_complete_cb_handle);
159 #else
160  st = __skelcap->RegisterCalibrationCallbacks(cb_calibration_start,
161  cb_calibration_end,
162  this, __calib_cb_handle);
163 #endif
164 
165  if (st != XN_STATUS_OK) {
166  throw Exception("Failed to register calibration callback (%s)",
167  xnGetStatusString(st));
168  }
169 
170  __skel_need_calib_pose = __skelcap->NeedPoseForCalibration();
171 
172  if (__skel_need_calib_pose) {
173  if (! __user_gen->IsCapabilitySupported(XN_CAPABILITY_POSE_DETECTION)) {
174  throw Exception("Calibration requires pose, but not supported by node");
175  }
176  __skelcap->GetCalibrationPose(__calib_pose_name);
177 
178  xn::PoseDetectionCapability posecap = __user_gen->GetPoseDetectionCap();
179 
180 #if XN_VERSION_GE(1,3,2,0)
181  st = posecap.RegisterToPoseDetected(cb_pose_start,
182  this, __pose_start_cb_handle);
183  if (st != XN_STATUS_OK) {
184  throw Exception("Failed to register pose detect event (%s)",
185  xnGetStatusString(st));
186  }
187  st = posecap.RegisterToOutOfPose(cb_pose_end,
188  this, __pose_end_cb_handle);
189 #else
190  st = posecap.RegisterToPoseCallbacks(cb_pose_start, cb_pose_end,
191  this, __pose_cb_handle);
192 #endif
193  if (st != XN_STATUS_OK) {
194  throw Exception("Failed to register pose callbacks (%s)", xnGetStatusString(st));
195  }
196  }
197 
198  __skelcap->SetSkeletonProfile(XN_SKEL_PROFILE_ALL);
199 
200  __depth_gen->StartGenerating();
201  __user_gen->StartGenerating();
202 
203  __label_buf = new SharedMemoryImageBuffer("openni-labels", RAW16,
204  __scene_md->XRes(),
205  __scene_md->YRes());
206  __label_bufsize = colorspace_buffer_size(RAW16,
207  __scene_md->XRes(), __scene_md->YRes());
208 
209  usergen_autoptr.release();
210  depthgen_autoptr.release();
211  scenemd_autoptr.release();
212 }
213 
214 
215 void
217 {
218  // we do not stop generating, we don't know if there is no other plugin
219  // using the node.
220  delete __user_gen;
221  delete __scene_md;
222  delete __skelcap;
223  delete __label_buf;
224 
225  UserMap::iterator i;
226  for (i = __users.begin(); i != __users.end(); ++i) {
227  blackboard->close(i->second.skel_if);
228  blackboard->close(i->second.proj_if);
229  }
230 }
231 
232 
233 void
235 {
236  // we do not lock here, we are only operating on our user generator copy
237  // and the update happens in a different main loop hook
238 
239  if (! __user_gen->IsDataNew()) return;
240 
241  UserMap::iterator i;
242  for (i = __users.begin(); i != __users.end(); ++i) {
243 
244  if (!i->second.valid) continue;
245 
246  bool needs_write = false;
247 
248  HumanSkeletonInterface::State new_state = i->second.skel_if->state();
249  if (__skelcap->IsTracking(i->first)) {
250  new_state = HumanSkeletonInterface::STATE_TRACKING;
251  } else if (__skelcap->IsCalibrating(i->first)) {
252  new_state = HumanSkeletonInterface::STATE_CALIBRATING;
253  } else {
254  new_state = HumanSkeletonInterface::STATE_DETECTING_POSE;
255  }
256 
257  if (new_state != i->second.skel_if->state()) {
258  i->second.skel_if->set_state(new_state);
259  needs_write = true;
260  }
261 
262  if (new_state == HumanSkeletonInterface::STATE_TRACKING) {
263  // update skeleton information
264  try {
265  update_user(i->first, i->second);
266  update_com(i->first, i->second);
267  needs_write = true;
268  } catch (Exception &e) {
269  logger->log_warn(name(), "Failed to update skeleton data for %u, "
270  "exception follows", i->first);
271  logger->log_warn(name(), e);
272  }
273  } else if (new_state == HumanSkeletonInterface::STATE_DETECTING_POSE) {
274  update_com(i->first, i->second);
275  needs_write = true;
276  } else if (new_state == HumanSkeletonInterface::STATE_CALIBRATING) {
277  update_com(i->first, i->second);
278  needs_write = true;
279  }
280 
281  if (needs_write) {
282  i->second.skel_if->write();
283  i->second.proj_if->write();
284  }
285  }
286 
287  if (__label_buf->num_attached() > 1) {
288  memcpy(__label_buf->buffer(), __scene_md->Data(), __label_bufsize);
289  }
290 
291 }
292 
293 
294 
295 
296 // Very noisy when added to st != XN_STATUS_OK case
297 //logger->log_warn(name(), "Failed to get joint transformation for "
298 // "%s joint (%s)",
299 // joint_name, xnGetStatusString(st));
300 
301 
302 // change from mm to m
303 // translating to Fawkes coordinates, empirically verified
304 // permute ori columns to match our coordinate system, empirically verified
305 #define SET_JTF(id, joint, joint_name, bbfield) \
306  st = __skelcap->GetSkeletonJoint(id, joint, jtf); \
307  if (st != XN_STATUS_OK) { \
308  ori[0] = ori[1] = ori[2] = ori[3] = ori[4] = ori[5] = 0.; \
309  ori[6] = ori[7] = ori[8] = ori_confidence = pos_confidence = 0.; \
310  proj[0] = proj[1] = 0; \
311  } else { \
312  pos[0] = jtf.position.position.Z * 0.001; \
313  pos[1] = -jtf.position.position.X * 0.001; \
314  pos[2] = jtf.position.position.Y * 0.001; \
315  pos_confidence = jtf.position.fConfidence; \
316  \
317  ori[0] = jtf.orientation.orientation.elements[2]; \
318  ori[1] = -jtf.orientation.orientation.elements[0]; \
319  ori[2] = jtf.orientation.orientation.elements[1]; \
320  ori[3] = jtf.orientation.orientation.elements[5]; \
321  ori[4] = -jtf.orientation.orientation.elements[3]; \
322  ori[5] = jtf.orientation.orientation.elements[4]; \
323  ori[6] = jtf.orientation.orientation.elements[8]; \
324  ori[7] = -jtf.orientation.orientation.elements[6]; \
325  ori[8] = jtf.orientation.orientation.elements[7]; \
326  ori_confidence = jtf.orientation.fConfidence; \
327  \
328  XnPoint3D pt; \
329  pt = jtf.position.position; \
330  __depth_gen->ConvertRealWorldToProjective(1, &pt, &pt); \
331  proj[0] = pt.X; \
332  proj[1] = pt.Y; \
333  } \
334  user.skel_if->set_pos_##bbfield(pos); \
335  user.skel_if->set_pos_##bbfield##_confidence(pos_confidence); \
336  user.skel_if->set_ori_##bbfield(ori); \
337  user.skel_if->set_ori_##bbfield##_confidence(ori_confidence); \
338  \
339  user.proj_if->set_proj_##bbfield(proj);
340 
341 
342 
343 void
344 OpenNiUserTrackerThread::update_user(XnUserID id, UserInfo &user)
345 {
346  XnSkeletonJointTransformation jtf;
347  XnStatus st;
348 
349  float pos[3], ori[9], proj[2], pos_confidence, ori_confidence;
350 
351  SET_JTF(id, XN_SKEL_HEAD, "head", head);
352  SET_JTF(id, XN_SKEL_NECK, "neck", neck);
353  SET_JTF(id, XN_SKEL_TORSO, "torso", torso);
354  SET_JTF(id, XN_SKEL_WAIST, "waist", waist);
355  SET_JTF(id, XN_SKEL_LEFT_COLLAR, "left collar", left_collar);
356  SET_JTF(id, XN_SKEL_LEFT_SHOULDER, "left shoulder", left_shoulder);
357  SET_JTF(id, XN_SKEL_LEFT_ELBOW, "left elbow", left_elbow);
358  SET_JTF(id, XN_SKEL_LEFT_WRIST, "left wrist", left_wrist);
359  SET_JTF(id, XN_SKEL_LEFT_HAND, "left hand", left_hand);
360  SET_JTF(id, XN_SKEL_LEFT_FINGERTIP, "left finger tip", left_fingertip);
361  SET_JTF(id, XN_SKEL_RIGHT_COLLAR, "right collar", right_collar);
362  SET_JTF(id, XN_SKEL_RIGHT_SHOULDER, "right shoulder", right_shoulder);
363  SET_JTF(id, XN_SKEL_RIGHT_ELBOW, "right elbow", right_elbow);
364  SET_JTF(id, XN_SKEL_RIGHT_WRIST, "right wrist", right_wrist);
365  SET_JTF(id, XN_SKEL_RIGHT_HAND, "right hand", right_hand);
366  SET_JTF(id, XN_SKEL_RIGHT_FINGERTIP, "right finger tip", right_fingertip);
367  SET_JTF(id, XN_SKEL_LEFT_HIP, "left hip", left_hip);
368  SET_JTF(id, XN_SKEL_LEFT_KNEE, "left knee", left_knee);
369  SET_JTF(id, XN_SKEL_LEFT_ANKLE, "left ankle", left_ankle);
370  SET_JTF(id, XN_SKEL_LEFT_FOOT, "left foot", left_foot);
371  SET_JTF(id, XN_SKEL_RIGHT_HIP, "right hip", right_hip);
372  SET_JTF(id, XN_SKEL_RIGHT_KNEE, "right knee", right_knee);
373  SET_JTF(id, XN_SKEL_RIGHT_ANKLE, "right ankle", right_ankle);
374  SET_JTF(id, XN_SKEL_RIGHT_FOOT, "right foot", right_foot);
375 
376 }
377 
378 
379 void
380 OpenNiUserTrackerThread::update_com(XnUserID id, UserInfo &user)
381 {
382  XnPoint3D compt, compt_proj;
383  XnStatus st;
384  float com[3], com_proj[2];
385  com[0] = com[1] = com[2] = com_proj[0] = com_proj[1] = 0.;
386  if ((st = __user_gen->GetCoM(id, compt)) == XN_STATUS_OK) {
387 
388  // translating to Fawkes coordinates, empirically verified
389  com[0] = compt.Z * 0.001;
390  com[1] = -compt.X * 0.001;
391  com[2] = compt.Y * 0.001;
392 
393  __depth_gen->ConvertRealWorldToProjective(1, &compt, &compt_proj);
394  com_proj[0] = compt_proj.X;
395  com_proj[1] = compt_proj.Y;
396  } else {
397  logger->log_warn(name(), "GetCoM failed: %s", xnGetStatusString(st));
398  }
399 
400  user.skel_if->set_com(com);
401  user.proj_if->set_proj_com(com_proj);
402 
403  int current_vishist = user.skel_if->visibility_history();
404  if ((com[0] == 0.) && (com[1] == 0.) && (com[2] == 0.)) {
405  if (current_vishist < 0) {
406  user.skel_if->set_visibility_history(--current_vishist);
407  } else {
408  user.skel_if->set_visibility_history(-1);
409  }
410  } else {
411  if (current_vishist > 0) {
412  user.skel_if->set_visibility_history(++current_vishist);
413  } else {
414  user.skel_if->set_visibility_history(1);
415  }
416  }
417 }
418 
419 /** Notify of new user.
420  * This is called by the OpenNI callback when a new user has been detected.
421  * @param id new user's ID
422  */
423 void
425 {
426  if (__users.find(id) != __users.end()) {
427  logger->log_error(name(), "New user ID %u, interface already exists", id);
428  } else {
429  char *ifid;
430  if (asprintf(&ifid, "OpenNI Human %u", id) == -1) {
431  logger->log_warn(name(), "New user ID %u, but cannot generate "
432  "interface ID", id);
433  return;
434  }
435  try {
436  logger->log_debug(name(), "Opening interface 'HumanSkeletonInterface::%s'", ifid);
437  __users[id].skel_if = blackboard->open_for_writing<HumanSkeletonInterface>(ifid);
438  __users[id].skel_if->set_user_id(id);
439  __users[id].skel_if->write();
440  } catch (Exception &e) {
441  logger->log_warn(name(), "Failed to open interface, exception follows");
442  logger->log_warn(name(), e);
443  }
444 
445  try {
446  logger->log_debug(name(), "Opening interface 'HumanSkeletonProjectionInterface::%s'", ifid);
447  __users[id].proj_if = blackboard->open_for_writing<HumanSkeletonProjectionInterface>(ifid);
448  XnFieldOfView fov;
449  XnStatus st;
450  if ((st = __depth_gen->GetFieldOfView(fov)) != XN_STATUS_OK) {
451  logger->log_error(name(), "Failed to get field of view, ignoring. (%s)",
452  xnGetStatusString(st));
453  } else {
454  __users[id].proj_if->set_horizontal_fov(fov.fHFOV);
455  __users[id].proj_if->set_vertical_fov(fov.fVFOV);
456  }
457 
458  xn::DepthMetaData dmd;
459  __depth_gen->GetMetaData(dmd);
460  __users[id].proj_if->set_res_x(dmd.XRes());
461  __users[id].proj_if->set_res_y(dmd.YRes());
462  __users[id].proj_if->set_max_depth(__depth_gen->GetDeviceMaxDepth());
463  __users[id].proj_if->write();
464  } catch (Exception &e) {
465  blackboard->close(__users[id].proj_if);
466  __users.erase(id);
467  logger->log_warn(name(), "Failed to open interface, exception follows");
468  logger->log_warn(name(), e);
469  }
470 
471  free(ifid);
472  }
473 
474  __users[id].valid = true;
475 
476  if (__skel_need_calib_pose) {
477  __user_gen->GetPoseDetectionCap().StartPoseDetection(__calib_pose_name, id);
478  } else {
479  __user_gen->GetSkeletonCap().RequestCalibration(id, TRUE);
480  }
481 }
482 
483 
484 /** Notify of lost user.
485  * This is called by the OpenNI callback when a user has been lost,
486  * i.e. it has not been visible for some time.
487  * @param id lost user's ID
488  */
489 void
491 {
492  if (__users.find(id) == __users.end()) {
493  logger->log_error(name(), "Lost user ID %u, but interface does not exist", id);
494  return;
495  }
496 
497  logger->log_error(name(), "Lost user ID %u, setting interface '%s' to invalid",
498  id, __users[id].skel_if->uid());
499  // write invalid, a reader might still be open
500  __users[id].skel_if->set_state(HumanSkeletonInterface::STATE_INVALID);
501  __users[id].skel_if->write();
502  __users[id].valid = false;
503  //blackboard->close(__users[id].skel_if);
504  //blackboard->close(__users[id].proj_if);
505  //__users.erase(id);
506 }
507 
508 
509 /** Notify of detected pose.
510  * This is called if a pose has been detected.
511  * @param id ID of user who is in the pose
512  * @param pose_name name of the detected pose
513  */
514 void
515 OpenNiUserTrackerThread::pose_start(XnUserID id, const char *pose_name)
516 {
517  if (__users.find(id) == __users.end()) {
518  logger->log_error(name(), "Pose start for user ID %u, "
519  "but interface does not exist", id);
520  return;
521  }
522 
523  logger->log_info(name(), "Pose %s detected for user %u", pose_name, id);
524 
525  __users[id].skel_if->set_pose(pose_name);
526  __user_gen->GetPoseDetectionCap().StopPoseDetection(id);
527  __user_gen->GetSkeletonCap().RequestCalibration(id, TRUE);
528 }
529 
530 /** Notify of pose detection end.
531  * This is called if a pose is no longer detected. The NITE middleware seems
532  * not to call this.
533  * @param id ID of user who is in the pose
534  * @param pose_name name of the no longer detected pose
535  */
536 void
537 OpenNiUserTrackerThread::pose_end(XnUserID id, const char *pose_name)
538 {
539  if (__users.find(id) == __users.end()) {
540  logger->log_error(name(), "Pose end for user ID %u, "
541  "but interface does not exist", id);
542  return;
543  }
544 
545  __users[id].skel_if->set_pose("");
546 }
547 
548 /** Notify of calibration start.
549  * This is called when tracking for a user has been started.
550  * @param id ID of user who is being calibrated.
551  */
552 void
554 {
555  if (__users.find(id) == __users.end()) {
556  logger->log_error(name(), "Pose end for user ID %u, "
557  "but interface does not exist", id);
558  return;
559  }
560 
561  logger->log_info(name(), "Calibration started for user %u", id);
562 }
563 
564 
565 /** Notify of calibration end.
566  * This is called when tracking for a user has finished.
567  * @param id ID of user who was being calibrated
568  * @param success true if the calibration was successful, false otherwise
569  */
570 void
572 {
573  if (__users.find(id) == __users.end()) {
574  logger->log_error(name(), "Pose end for user ID %u, "
575  "but interface does not exist", id);
576  return;
577  }
578 
579  __users[id].skel_if->set_pose("");
580 
581  if (success) {
582  logger->log_info(name(), "Calibration successful for user %u, "
583  "starting tracking", id);
584  __user_gen->GetSkeletonCap().StartTracking(id);
585  } else {
586  logger->log_info(name(), "Calibration failed for user %u, restarting", id);
587  if (__skel_need_calib_pose) {
588  __user_gen->GetPoseDetectionCap().StartPoseDetection(__calib_pose_name, id);
589  } else {
590  __user_gen->GetSkeletonCap().RequestCalibration(id, TRUE);
591  }
592  }
593 }
LockPtr< xn::Context > openni
Central OpenNI context.
Definition: openni.h:48
HumanSkeletonProjectionInterface Fawkes BlackBoard Interface.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
virtual ~OpenNiUserTrackerThread()
Destructor.
void new_user(XnUserID id)
Notify of new user.
Fawkes library namespace.
Mutex locking helper.
Definition: mutex_locker.h:33
Thread class encapsulation of pthreads.
Definition: thread.h:42
void calibration_end(XnUserID id, bool success)
Notify of calibration end.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:44
void pose_end(XnUserID id, const char *pose_name)
Notify of pose detection end.
virtual void init()
Initialize the thread.
unsigned char * buffer() const
Get image buffer.
Definition: shm_image.cpp:235
State
Current tracking state for the skeleton.
Thread aspect to use blocked timing.
virtual void finalize()
Finalize the thread.
Base class for exceptions in Fawkes.
Definition: exception.h:36
Mutex * objmutex_ptr() const
Get object mutex.
Definition: lockptr.h:262
OpenNiUserTrackerThread()
Constructor.
Shared memory image buffer.
Definition: shm_image.h:181
unsigned int num_attached() const
Get number of attached processes.
Definition: shm.cpp:714
const char * name() const
Get name of thread.
Definition: thread.h:95
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
virtual void loop()
Code to execute in the thread.
void lost_user(XnUserID id)
Notify of lost user.
OpenNI User Tracker Thread.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
HumanSkeletonInterface Fawkes BlackBoard Interface.
void pose_start(XnUserID id, const char *pose_name)
Notify of detected pose.
void calibration_start(XnUserID id)
Notify of calibration start.
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:44
virtual Interface * open_for_writing(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for writing.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
Definition: blackboard.h:44
virtual void close(Interface *interface)=0
Close interface.