hornetseye-kinect 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -58,3 +58,42 @@ You can load and use the libfreenect wrappers as shown below. This example demon
58
58
  end
59
59
  end
60
60
 
61
+ Here is another example displaying RGB and the depth image while keeping the tilt angle at zero:
62
+
63
+ require 'rubygems'
64
+ require 'hornetseye_kinect'
65
+ require 'hornetseye_xorg'
66
+ include Hornetseye
67
+ class Numeric
68
+ def clip( range )
69
+ [ [ self, range.begin ].max, range.end ].min
70
+ end
71
+ end
72
+ colours = Sequence.ubytergb 256
73
+ for i in 0...256
74
+ hue = 240 - i * 240.0 / 256.0
75
+ colours[i] =
76
+ RGB( ( ( hue - 180 ).abs - 60 ).clip( 0...60 ) * 0xFF / 60.0,
77
+ ( 120 - ( hue - 120 ).abs ).clip( 0...60 ) * 0xFF / 60.0,
78
+ ( 120 - ( hue - 240 ).abs ).clip( 0...60 ) * 0xFF / 60.0 )
79
+ end
80
+ input = KinectInput.new
81
+ display = X11Display.new
82
+ output_depth, output_video = XImageOutput.new, XVideoOutput.new
83
+ window_depth = X11Window.new display, output_depth, 640, 480
84
+ window_video = X11Window.new display, output_video, 640, 480
85
+ window_depth.title = 'Depth'
86
+ window_video.title = 'Video'
87
+ window_depth.show
88
+ window_video.show
89
+ input.led = KinectInput::LED_RED
90
+ while display.status?
91
+ input.tilt = 0.0
92
+ input.get_state
93
+ moving = input.tilt_status == KinectInput::TILT_STATUS_MOVING
94
+ input.led = moving ? KinectInput::LED_RED : KinectInput::LED_GREEN
95
+ output_video.write input.read_video
96
+ output_depth.write( ( input.read_depth >> 3 ).lut colours )
97
+ display.process_events
98
+ end
99
+
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'rake/loaders/makefile'
7
7
  require 'rbconfig'
8
8
 
9
9
  PKG_NAME = 'hornetseye-kinect'
10
- PKG_VERSION = '0.1.0'
10
+ PKG_VERSION = '0.2.0'
11
11
  CFG = RbConfig::CONFIG
12
12
  CXX = ENV[ 'CXX' ] || 'g++'
13
13
  RB_FILES = FileList[ 'lib/**/*.rb' ]
data/ext/kinectcontext.cc CHANGED
@@ -26,7 +26,8 @@ using namespace std;
26
26
  VALUE KinectContext::cRubyClass = Qnil;
27
27
 
28
28
  KinectContext::KinectContext(void) throw (Error):
29
- m_context(NULL)
29
+ m_context(NULL), m_mutex(PTHREAD_MUTEX_INITIALIZER), m_cond(PTHREAD_COND_INITIALIZER),
30
+ m_instances(0)
30
31
  {
31
32
  freenect_init( &m_context, NULL );
32
33
  ERRORMACRO( m_context != NULL, Error, , "Initialisation of libfreenect failed" );
@@ -37,9 +38,28 @@ KinectContext::~KinectContext(void)
37
38
  close();
38
39
  }
39
40
 
41
+ void KinectContext::addInstance(void)
42
+ {
43
+ m_instances++;
44
+ if ( m_instances == 1 ) {
45
+ pthread_create( &m_thread, NULL, staticThreadFunc, this );
46
+ };
47
+ }
48
+
49
+ void KinectContext::removeInstance(void)
50
+ {
51
+ m_instances--;
52
+ if ( m_instances == 0 ) {
53
+ pthread_cond_wait( &m_cond, &m_mutex );
54
+ }
55
+ }
56
+
40
57
  void KinectContext::close(void)
41
58
  {
42
59
  if ( m_context != NULL ) {
60
+ pthread_join( m_thread, NULL );
61
+ pthread_mutex_destroy( &m_mutex );
62
+ pthread_cond_destroy( &m_cond );
43
63
  freenect_shutdown( m_context );
44
64
  m_context = NULL;
45
65
  };
@@ -52,6 +72,21 @@ freenect_context *KinectContext::get(void) throw (Error)
52
72
  return m_context;
53
73
  }
54
74
 
75
+ void KinectContext::lock(void)
76
+ {
77
+ pthread_mutex_lock( &m_mutex );
78
+ }
79
+
80
+ void KinectContext::wait(void)
81
+ {
82
+ processEvents();
83
+ }
84
+
85
+ void KinectContext::unlock(void)
86
+ {
87
+ pthread_mutex_unlock( &m_mutex );
88
+ }
89
+
55
90
  void KinectContext::processEvents(void) throw (Error)
56
91
  {
57
92
  ERRORMACRO( freenect_process_events( m_context ) >= 0, Error, , "Error processing "
@@ -65,6 +100,27 @@ string KinectContext::inspect(void) const
65
100
  return s.str();
66
101
  }
67
102
 
103
+ void KinectContext::threadFunc(void)
104
+ {
105
+ bool quit = false;
106
+ while ( !quit ) {
107
+ lock();
108
+ if ( m_instances > 0 )
109
+ processEvents();
110
+ else {
111
+ pthread_cond_signal( &m_cond );
112
+ quit = true;
113
+ };
114
+ unlock();
115
+ };
116
+ }
117
+
118
+ void *KinectContext::staticThreadFunc( void *self )
119
+ {
120
+ ((KinectContext *)self)->threadFunc();
121
+ return self;
122
+ }
123
+
68
124
  VALUE KinectContext::registerRubyClass( VALUE module )
69
125
  {
70
126
  cRubyClass = rb_define_class_under( module, "KinectContext", rb_cObject );
data/ext/kinectcontext.hh CHANGED
@@ -28,15 +28,26 @@ public:
28
28
  virtual ~KinectContext(void);
29
29
  std::string inspect(void) const;
30
30
  void close(void);
31
+ void addInstance(void);
32
+ void removeInstance(void);
31
33
  void processEvents(void) throw (Error);
32
34
  freenect_context *get(void) throw (Error);
35
+ void lock(void);
36
+ void wait(void);
37
+ void unlock(void);
33
38
  static VALUE cRubyClass;
34
39
  static VALUE registerRubyClass( VALUE module );
35
40
  static void deleteRubyObject( void *ptr );
36
41
  static VALUE wrapNew( VALUE rbClass );
37
42
  static VALUE wrapClose( VALUE rbSelf );
38
43
  protected:
44
+ void threadFunc(void);
45
+ static void *staticThreadFunc( void *self );
39
46
  freenect_context *m_context;
47
+ pthread_t m_thread;
48
+ pthread_mutex_t m_mutex;
49
+ pthread_cond_t m_cond;
50
+ int m_instances;
40
51
  };
41
52
 
42
53
  typedef boost::shared_ptr< KinectContext > KinectContextPtr;
data/ext/kinectinput.cc CHANGED
@@ -25,13 +25,16 @@ KinectInput::KinectInput( KinectContextPtr context, int node ) throw (Error):
25
25
  m_context( context ), m_node( node ), m_device( NULL ), m_currentRGB(0), m_haveRGB(false),
26
26
  m_currentDepth(0), m_haveDepth(false)
27
27
  {
28
- m_rgb[0] = NULL; m_rgb[1] = NULL; m_depth[0] = NULL; m_depth[1] = NULL;
29
- ERRORMACRO( freenect_open_device( context->get(), &m_device, node ) >= 0, Error, ,
30
- "Failed to open Kinect device number " << node );
31
- m_rgb[0] = (char *)malloc( FREENECT_VIDEO_RGB_SIZE );
32
- m_rgb[1] = (char *)malloc( FREENECT_VIDEO_RGB_SIZE );
33
- m_depth[0] = (char *)malloc( FREENECT_DEPTH_11BIT_SIZE );
34
- m_depth[1] = (char *)malloc( FREENECT_DEPTH_11BIT_SIZE );
28
+ memset( &m_rgb, 0, sizeof(m_rgb) ); memset( &m_depth, 0, sizeof(m_depth) );
29
+ m_context->lock();
30
+ if ( freenect_open_device( context->get(), &m_device, node ) < 0 ) {
31
+ m_context->unlock();
32
+ ERRORMACRO( false, Error, , "Failed to open Kinect device number " << node );
33
+ };
34
+ for ( int i=0; i<3; i++ ) {
35
+ m_rgb[i] = (char *)malloc( FREENECT_VIDEO_RGB_SIZE );
36
+ m_depth[i] = (char *)malloc( FREENECT_DEPTH_11BIT_SIZE );
37
+ };
35
38
  instances[ m_device ] = this;
36
39
  freenect_set_depth_format( m_device, FREENECT_DEPTH_11BIT );
37
40
  freenect_set_video_format( m_device, FREENECT_VIDEO_RGB );
@@ -41,6 +44,8 @@ KinectInput::KinectInput( KinectContextPtr context, int node ) throw (Error):
41
44
  freenect_set_video_callback( m_device, staticVideoCallBack );
42
45
  freenect_start_depth( m_device );
43
46
  freenect_start_video( m_device );
47
+ m_context->addInstance();
48
+ m_context->unlock();
44
49
  }
45
50
 
46
51
  KinectInput::~KinectInput(void)
@@ -51,29 +56,26 @@ KinectInput::~KinectInput(void)
51
56
  void KinectInput::close(void)
52
57
  {
53
58
  if ( m_device != NULL ) {
59
+ m_context->lock();
54
60
  freenect_stop_depth( m_device );
55
61
  freenect_stop_video( m_device );
56
62
  freenect_set_led( m_device, LED_BLINK_GREEN );
57
63
  freenect_close_device( m_device );
58
64
  instances.erase( m_device );
65
+ m_context->removeInstance();
66
+ m_context->unlock();
59
67
  m_context.reset();
60
68
  m_device = NULL;
61
69
  };
62
- if ( m_depth[1] != NULL ) {
63
- free( m_depth[1] );
64
- m_depth[1] = NULL;
65
- };
66
- if ( m_depth[0] != NULL ) {
67
- free( m_depth[0] );
68
- m_depth[0] = NULL;
69
- };
70
- if ( m_rgb[1] != NULL ) {
71
- free( m_rgb[1] );
72
- m_rgb[1] = NULL;
73
- };
74
- if ( m_rgb[0] != NULL ) {
75
- free( m_rgb[0] );
76
- m_rgb[0] = NULL;
70
+ for ( int i=0; i<3; i++ ) {
71
+ if ( m_depth[i] != NULL ) {
72
+ free( m_depth[i] );
73
+ m_depth[i] = NULL;
74
+ };
75
+ if ( m_rgb[i] != NULL ) {
76
+ free( m_rgb[i] );
77
+ m_rgb[i] = NULL;
78
+ };
77
79
  };
78
80
  m_node = -1;
79
81
  }
@@ -82,11 +84,15 @@ FramePtr KinectInput::readVideo(void) throw (Error)
82
84
  {
83
85
  ERRORMACRO( m_device != NULL, Error, , "Kinect device is not open. "
84
86
  "Did you call \"close\" before?" );
85
- while ( !m_haveRGB ) m_context->processEvents();
87
+ m_context->lock();
88
+ while ( !m_haveRGB ) m_context->wait();
86
89
  m_haveRGB = false;
90
+ char *data = m_rgb[ 2 ];
91
+ m_rgb[ 2 ] = m_rgb[ 1 - m_currentRGB ];
92
+ m_rgb[ 1 - m_currentRGB ] = data;
93
+ m_context->unlock();
87
94
  FramePtr retVal = FramePtr
88
- ( new Frame( "UBYTERGB", FREENECT_FRAME_W, FREENECT_FRAME_H,
89
- m_rgb[ 1 - m_currentRGB ] ) );
95
+ ( new Frame( "UBYTERGB", FREENECT_FRAME_W, FREENECT_FRAME_H, m_rgb[ 2 ] ) );
90
96
  return retVal;
91
97
  }
92
98
 
@@ -94,11 +100,15 @@ FramePtr KinectInput::readDepth(void) throw (Error)
94
100
  {
95
101
  ERRORMACRO( m_device != NULL, Error, , "Kinect device is not open. "
96
102
  "Did you call \"close\" before?" );
97
- while ( !m_haveDepth ) m_context->processEvents();
103
+ m_context->lock();
104
+ while ( !m_haveDepth ) m_context->wait();
98
105
  m_haveDepth = false;
106
+ char *data = m_depth[ 2 ];
107
+ m_depth[ 2 ] = m_depth[ 1 - m_currentDepth ];
108
+ m_depth[ 1 - m_currentDepth ] = data;
109
+ m_context->unlock();
99
110
  FramePtr retVal = FramePtr
100
- ( new Frame( "USINT", FREENECT_FRAME_W, FREENECT_FRAME_H,
101
- m_depth[ 1 - m_currentDepth ] ) );
111
+ ( new Frame( "USINT", FREENECT_FRAME_W, FREENECT_FRAME_H, m_depth[ 2 ] ) );
102
112
  return retVal;
103
113
  }
104
114
 
@@ -118,16 +128,26 @@ void KinectInput::setLED( unsigned char state ) throw (Error)
118
128
  {
119
129
  ERRORMACRO( m_device != NULL, Error, , "Kinect device is not open. "
120
130
  "Did you call \"close\" before?" );
121
- ERRORMACRO( freenect_set_led( m_device, (freenect_led_options)state ) == 0, Error, ,
122
- "Error setting LED state" );
131
+ m_context->lock();
132
+ if ( freenect_set_led( m_device, (freenect_led_options)state ) == 0 ) {
133
+ m_context->unlock();
134
+ } else {
135
+ m_context->unlock();
136
+ ERRORMACRO( false, Error, , "Error setting LED state" );
137
+ };
123
138
  }
124
139
 
125
140
  void KinectInput::setTilt( double angle ) throw (Error)
126
141
  {
127
142
  ERRORMACRO( m_device != NULL, Error, , "Kinect device is not open. "
128
143
  "Did you call \"close\" before?" );
129
- ERRORMACRO( freenect_set_tilt_degs( m_device, angle ) == 0, Error, ,
130
- "Error setting tilt angle" );
144
+ m_context->lock();
145
+ if ( freenect_set_tilt_degs( m_device, angle ) == 0 ) {
146
+ m_context->unlock();
147
+ } else {
148
+ ERRORMACRO( false, Error, , "Error setting tilt angle" );
149
+ m_context->unlock();
150
+ };
131
151
  }
132
152
 
133
153
  void KinectInput::getState(void) throw (Error)
data/ext/kinectinput.hh CHANGED
@@ -63,10 +63,10 @@ public:
63
63
  freenect_device *m_device;
64
64
  int m_currentRGB;
65
65
  bool m_haveRGB;
66
- char *m_rgb[2];
66
+ char *m_rgb[3];
67
67
  int m_currentDepth;
68
68
  bool m_haveDepth;
69
- char *m_depth[2];
69
+ char *m_depth[3];
70
70
  };
71
71
 
72
72
  typedef boost::shared_ptr< KinectInput > KinectInputPtr;
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jan Wedekind
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-09 00:00:00 +00:00
17
+ date: 2011-03-11 00:00:00 +00:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency