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 +39 -0
- data/Rakefile +1 -1
- data/ext/kinectcontext.cc +57 -1
- data/ext/kinectcontext.hh +11 -0
- data/ext/kinectinput.cc +52 -32
- data/ext/kinectinput.hh +2 -2
- metadata +3 -3
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
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
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
122
|
-
|
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
|
-
|
130
|
-
|
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[
|
66
|
+
char *m_rgb[3];
|
67
67
|
int m_currentDepth;
|
68
68
|
bool m_haveDepth;
|
69
|
-
char *m_depth[
|
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
|
-
-
|
7
|
+
- 2
|
8
8
|
- 0
|
9
|
-
version: 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-
|
17
|
+
date: 2011-03-11 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|