00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #pragma once
00028
00029 #include <libfreenect.h>
00030 #include <stdexcept>
00031 #include <map>
00032 #include <pthread.h>
00033
00034 namespace Freenect {
00035 class Noncopyable {
00036 public:
00037 Noncopyable() {}
00038 ~Noncopyable() {}
00039 private:
00040 Noncopyable( const Noncopyable& );
00041 const Noncopyable& operator=( const Noncopyable& );
00042 };
00043
00044 class FreenectDeviceState : Noncopyable {
00045 friend class FreenectDevice;
00046 FreenectDeviceState(freenect_raw_device_state *_state):
00047 m_state(_state)
00048 {}
00049 public:
00050 void getAccelerometers(double* x, double* y, double* z) {
00051 freenect_get_mks_accel(m_state, x, y, z);
00052 }
00053 double getTiltDegs() {
00054 return freenect_get_tilt_degs(m_state);
00055 }
00056 private:
00057 freenect_raw_device_state *m_state;
00058 };
00059
00060 class FreenectDevice : Noncopyable {
00061 public:
00062 FreenectDevice(freenect_context *_ctx, int _index) {
00063 if(freenect_open_device(_ctx, &m_dev, _index) != 0) throw std::runtime_error("Cannot open Kinect");
00064 freenect_set_user(m_dev, this);
00065 freenect_set_rgb_format(m_dev, FREENECT_FORMAT_RGB);
00066 freenect_set_depth_format(m_dev, FREENECT_FORMAT_11_BIT);
00067 freenect_set_depth_callback(m_dev, freenect_depth_callback);
00068 freenect_set_rgb_callback(m_dev, freenect_rgb_callback);
00069 }
00070 ~FreenectDevice() {
00071 if(freenect_close_device(m_dev) != 0) throw std::runtime_error("Cannot shutdown Kinect");
00072 }
00073 void startRGB() {
00074 if(freenect_start_rgb(m_dev) != 0) throw std::runtime_error("Cannot start RGB callback");
00075 }
00076 void stopRGB() {
00077 if(freenect_stop_rgb(m_dev) != 0) throw std::runtime_error("Cannot stop RGB callback");
00078 }
00079 void startDepth() {
00080 if(freenect_start_depth(m_dev) != 0) throw std::runtime_error("Cannot start depth callback");
00081 }
00082 void stopDepth() {
00083 if(freenect_stop_depth(m_dev) != 0) throw std::runtime_error("Cannot stop depth callback");
00084 }
00085 void setTiltDegrees(double _angle) {
00086 if(freenect_set_tilt_degs(m_dev, _angle) != 0) throw std::runtime_error("Cannot set angle in degrees");
00087 }
00088 void setLed(freenect_led_options _option) {
00089 if(freenect_set_led(m_dev, _option) != 0) throw std::runtime_error("Cannot set led");
00090 }
00091 void updateState() {
00092 if (freenect_update_device_state(m_dev) != 0) throw std::runtime_error("Cannot update device state");
00093 }
00094 FreenectDeviceState getState() const {
00095 return FreenectDeviceState(freenect_get_device_state(m_dev));
00096 }
00097
00098 virtual void RGBCallback(freenect_pixel *rgb, uint32_t timestamp) = 0;
00099
00100 virtual void DepthCallback(freenect_depth *depth, uint32_t timestamp) = 0;
00101 private:
00102 freenect_device *m_dev;
00103 static void freenect_depth_callback(freenect_device *dev, freenect_depth *depth, uint32_t timestamp) {
00104 FreenectDevice* device = static_cast<FreenectDevice*>(freenect_get_user(dev));
00105 device->DepthCallback(depth, timestamp);
00106 }
00107 static void freenect_rgb_callback(freenect_device *dev, freenect_pixel *rgb, uint32_t timestamp) {
00108 FreenectDevice* device = static_cast<FreenectDevice*>(freenect_get_user(dev));
00109 device->RGBCallback(rgb, timestamp);
00110 }
00111 };
00112
00113 template <class T>class Freenect : Noncopyable {
00114 public:
00115 Freenect() : m_stop(false) {
00116 if(freenect_init(&m_ctx, NULL) != 0) throw std::runtime_error("Cannot initialize freenect library");
00117 if(pthread_create(&m_thread, NULL, pthread_callback, (void*)this) != 0) throw std::runtime_error("Cannot initialize freenect thread");
00118 }
00119 ~Freenect() {
00120 for(typename std::map<int, T*>::iterator it = m_devices.begin() ; it != m_devices.end() ; ++it) {
00121 delete it->second;
00122 }
00123 m_stop = true;
00124 pthread_join(m_thread, NULL);
00125 if(freenect_shutdown(m_ctx) != 0) throw std::runtime_error("Cannot cleanup freenect library");
00126 }
00127 T& createDevice(int _index) {
00128 m_devices.insert(std::make_pair<int, T*>(_index, new T(m_ctx, _index)));
00129 return *(m_devices.at(_index));
00130 }
00131 void deleteDevice(int _index) {
00132 m_devices.erase(_index);
00133 }
00134 int deviceCount() {
00135 return freenect_num_devices(m_ctx);
00136 }
00137
00138 void operator()() {
00139 while(!m_stop) {
00140 if(freenect_process_events(m_ctx) != 0) throw std::runtime_error("Cannot process freenect events");
00141 }
00142 }
00143 static void *pthread_callback(void *user_data) {
00144 Freenect<T>* freenect = static_cast<Freenect<T>*>(user_data);
00145 (*freenect)();
00146 }
00147 private:
00148 freenect_context *m_ctx;
00149 volatile bool m_stop;
00150 pthread_t m_thread;
00151 std::map<int, T*> m_devices;
00152 };
00153
00154 }
00155