hornetseye-kinect 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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