freenect.cpp
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <assert.h>
00005 #include <math.h>
00006 #include <sys/time.h>
00007 #include <unistd.h>
00008 #include <inttypes.h>
00009 
00010 #include <pthread.h>
00011 
00012 #include <zlib.h>
00013 #include <glib.h>
00014 #include <lcm/lcm.h>
00015 #include <libfreenect.h>
00016 
00017 #include <lcmtypes/kinect_depth_msg_t.h>
00018 #include <lcmtypes/kinect_image_msg_t.h>
00019 #include <lcmtypes/kinect_frame_msg_t.h>
00020 #include <lcmtypes/kinect_cmd_msg_t.h>
00021 #include <lcmtypes/kinect_sensor_status_t.h>
00022 
00023 #if USE_JPEG_UTILS_POD
00024 #include <jpeg-utils/jpeg-utils.h>
00025 #else
00026 #include "jpeg-utils-ijg.h"
00027 #endif
00028 
00029 #include "timestamp.h"
00030 #include "pixels.h"
00031 
00032 #define dbg(...) fprintf(stderr, __VA_ARGS__)
00033 
00034 #define alpha 0.05 //decay rate for the moving average
00035 typedef struct _rate_t {
00036     double target_hz;
00037     double current_hz;
00038     int64_t last_tick;
00039     int64_t tick_count;
00040 } rate_t;
00041 
00042 rate_t* rate_new(double target_hz);
00043 
00044 void rate_destroy(rate_t* rate);
00045 
00049 int rate_check(rate_t* rate);
00050 
00051 typedef struct _state_t {
00052     GThread* freenect_thread;
00053     volatile int die;
00054 
00055     freenect_context *f_ctx;
00056     freenect_device *f_dev;
00057     int freenect_angle;
00058     int freenect_led;
00059 
00060     int8_t requested_image_format;
00061     int8_t current_image_format;
00062 
00063     int8_t requested_depth_format;
00064     int8_t current_depth_format;
00065 
00066     int8_t current_resolution;
00067 
00068     uint8_t* image_data;
00069 
00070     uint8_t* image_buf;
00071     int image_buf_size;
00072 
00073     uint8_t* debayer_buf;
00074     int debayer_buf_size;
00075 
00076     uint16_t* depth_unpack_buf;
00077     int depth_unpack_buf_size;
00078 
00079     uint8_t* depth_compress_buf;
00080     int debayer_buf_stride;
00081     int depth_compress_buf_size;
00082 
00083     freenect_raw_tilt_state* tilt_state;
00084     double accel_mks[3];
00085     double tilt_radians;
00086 
00087     int8_t current_led;
00088     int8_t requested_led;
00089 
00090     kinect_frame_msg_t msg;
00091     char* msg_channel;
00092 
00093     int got_img;
00094     int got_depth;
00095 
00096     int skip_img;
00097     int skip_depth;
00098     int throttle; //1 in data skip will be published
00099     timestamp_sync_state_t* clocksync;
00100 
00101     rate_t* capture_rate;
00102     rate_t* report_rate;
00103 
00104     uint8_t* jpeg_buf;
00105     int jpeg_buf_size;
00106 
00107     int jpeg_quality;
00108 
00109     int use_zlib;
00110 
00111     lcm_t* lcm;
00112 
00113     int64_t last_timestamp;
00114     int64_t last_depth_timestamp;
00115     int64_t last_img_timestamp;
00116 
00117     pthread_t  work_thread;
00118     
00119 } state_t;
00120 
00121 static void
00122 populate_status(state_t* state, kinect_frame_msg_t* msg, int64_t timestamp)
00123 {
00124     freenect_update_tilt_state(state->f_dev);
00125     state->tilt_state = freenect_get_tilt_state(state->f_dev);
00126 
00127     double dx, dy, dz;
00128     freenect_get_mks_accel(state->tilt_state, &dx, &dy, &dz);
00129 
00130     msg->timestamp = timestamp;
00131     msg->raw_accel[0] = state->tilt_state->accelerometer_x;
00132     msg->raw_accel[1] = state->tilt_state->accelerometer_y;
00133     msg->raw_accel[2] = state->tilt_state->accelerometer_z;
00134     msg->raw_tilt = state->tilt_state->tilt_angle;
00135 
00136     msg->accel[0] = dx;
00137     msg->accel[1] = dy;
00138 
00139     // XXX the kinect accelerometer appears to use a left-handed coordinate
00140     // frame, where Z points in towards the camera.  We could invert it here 
00141     // to make it more consistent with standard coordinate frames.
00142     msg->accel[2] = dz;
00143 
00144     msg->tilt_radians = freenect_get_tilt_degs(state->tilt_state) * M_PI / 180;
00145 
00146     msg->led_status = state->current_led;
00147 
00148     switch (state->tilt_state->tilt_status) {
00149     case TILT_STATUS_STOPPED:
00150         msg->tilt_status = KINECT_FRAME_MSG_T_TILT_STATUS_STOPPED;
00151         break;
00152     case TILT_STATUS_LIMIT:
00153         msg->tilt_status = KINECT_FRAME_MSG_T_TILT_STATUS_LIMIT;
00154         break;
00155     case TILT_STATUS_MOVING:
00156         msg->tilt_status = KINECT_FRAME_MSG_T_TILT_STATUS_MOVING;
00157         break;
00158     }
00159     msg->tilt_status = state->tilt_state->tilt_status;
00160 }
00161 
00162 rate_t* rate_new(double target_hz)
00163 {
00164     rate_t* rt = (rate_t *) calloc(1, sizeof(rate_t));
00165     rt->target_hz = target_hz;
00166     rt->tick_count = 0;
00167     return rt;
00168 }
00169 
00170 void rate_destroy(rate_t* rate)
00171 {
00172     free(rate);
00173 }
00174 
00175 int rate_check(rate_t* rate)
00176 {
00177     // check the current time
00178     int64_t c_utime = timestamp_now();
00179 
00180     // compute the framerate if we were to publish an image
00181     int64_t dt = c_utime - rate->last_tick;
00182 
00183     double p_framerate = alpha * (1.0 * 1e6 / dt) + (1 - alpha) * rate->current_hz;
00184     if (p_framerate > rate->target_hz) {
00185         // if the potential framerate is too high, don't publish, and return 0
00186         return 0;
00187     }
00188     else {
00189         // otherwise, update current_hz with a exponential moving average, and return 1
00190         rate->current_hz = p_framerate;
00191         rate->last_tick = c_utime;
00192         rate->tick_count++;
00193         return 1;
00194     }
00195 }
00196 
00197 static void
00198 set_image_depth_formats(state_t* state)
00199 {
00200     freenect_video_format vfmt;
00201     freenect_depth_format dfmt;
00202 
00203     switch (state->requested_image_format) {
00204     case KINECT_IMAGE_MSG_T_VIDEO_RGB:
00205     case KINECT_IMAGE_MSG_T_VIDEO_BAYER:
00206     case KINECT_IMAGE_MSG_T_VIDEO_IR_8BIT:
00207     case KINECT_IMAGE_MSG_T_VIDEO_IR_10BIT:
00208     case KINECT_IMAGE_MSG_T_VIDEO_IR_10BIT_PACKED:
00209     case KINECT_IMAGE_MSG_T_VIDEO_YUV_RAW:
00210         {
00211             vfmt = state->requested_image_format;
00212             freenect_frame_mode md = freenect_find_video_mode(state->current_resolution, state->requested_image_format);
00213             state->msg.image.image_data_nbytes = md.bytes;
00214         }
00215         break;
00216     case KINECT_IMAGE_MSG_T_VIDEO_RGB_JPEG:
00217         vfmt = FREENECT_VIDEO_BAYER;
00218         break;
00219     default:
00220         vfmt = FREENECT_VIDEO_BAYER;
00221         fprintf(stderr, "Invalid image format requested: %d\n", state->requested_image_format);
00222         state->msg.image.image_data_nbytes = 0;
00223         break;
00224     }
00225 
00226     switch (state->requested_depth_format) {
00227     case KINECT_DEPTH_MSG_T_DEPTH_11BIT:
00228     case KINECT_DEPTH_MSG_T_DEPTH_10BIT:
00229     case KINECT_DEPTH_MSG_T_DEPTH_11BIT_PACKED:
00230     case KINECT_DEPTH_MSG_T_DEPTH_10BIT_PACKED:
00231     case KINECT_DEPTH_MSG_T_DEPTH_REGISTERED:
00232     case KINECT_DEPTH_MSG_T_DEPTH_MM:
00233         dfmt = state->requested_depth_format;
00234         break;
00235     default:
00236         dfmt = FREENECT_DEPTH_11BIT_PACKED;
00237         fprintf(stderr, "Invalid depth format requested: %d\n", state->requested_depth_format);
00238         break;
00239     }
00240 
00241     state->current_image_format = state->requested_image_format;
00242     state->msg.image.image_data_format = state->requested_image_format;
00243     state->current_depth_format = state->requested_depth_format;
00244     state->msg.depth.depth_data_format = state->requested_depth_format;
00245 
00246     freenect_frame_mode vmode = freenect_find_video_mode(state->current_resolution, vfmt);
00247     freenect_frame_mode dmode = freenect_find_depth_mode(state->current_resolution, dfmt);
00248 
00249     freenect_set_video_mode(state->f_dev, vmode);
00250     freenect_set_depth_mode(state->f_dev, dmode);
00251 }
00252 
00253 void
00254 cmd_cb(const lcm_recv_buf_t *rbuf __attribute__((unused)),
00255        const char *channel __attribute__((unused)),
00256        const kinect_cmd_msg_t *msg,
00257        void *user)
00258 {
00259     state_t *self = (state_t *) user;
00260 
00261     if (msg->command_type == KINECT_CMD_MSG_T_SET_TILT) {
00262         dbg("Received tilt command; Angle : %d\n", msg->tilt_degree);
00263         self->freenect_angle = msg->tilt_degree;
00264 
00265         if (self->freenect_angle > 30)
00266             self->freenect_angle = 30;
00267         else if (self->freenect_angle < -20)
00268             self->freenect_angle = -20;
00269 
00270         // XXX is libfreenect thread-safe?
00271         freenect_set_tilt_degs(self->f_dev, self->freenect_angle);
00272     }
00273     else if (msg->command_type == KINECT_CMD_MSG_T_SET_LED) {
00274         // check that requested LED status is valid
00275         if (msg->led_status >= 0 && msg->led_status <= 6) {
00276             // XXX is libfreenect thread-safe?
00277             freenect_set_led(self->f_dev, msg->led_status);
00278         }
00279     }
00280     else if (msg->command_type == KINECT_CMD_MSG_T_SET_DEPTH_DATA_FORMAT) {
00281         // check that requested depth format is valid
00282         if (msg->depth_data_format >= 0 && msg->depth_data_format < 4) {
00283             self->requested_depth_format = msg->depth_data_format;
00284         }
00285     }
00286     else if (msg->command_type == KINECT_CMD_MSG_T_SET_IMAGE_DATA_FORMAT) {
00287         // TODO
00288     }
00289 }
00290 
00291 // Unpack buffer of (vw bit) data into padded 16bit buffer.
00292 static inline void
00293 convert_packed_to_16bit(uint8_t *raw, uint16_t *frame, int vw, int len)
00294 {
00295     int mask = (1 << vw) - 1;
00296     uint32_t buffer = 0;
00297     int bitsIn = 0;
00298     while (len--) {
00299         while (bitsIn < vw) {
00300             buffer = (buffer << 8) | *(raw++);
00301             bitsIn += 8;
00302         }
00303         bitsIn -= vw;
00304         *(frame++) = (buffer >> bitsIn) & mask;
00305     }
00306 }
00307 
00308 void
00309 depth_cb(freenect_device *dev, void *data, uint32_t timestamp)
00310 {
00311     state_t* state = (state_t*) freenect_get_user(dev);
00312     int64_t host_utime = timestamp_now();
00313     int64_t msg_utime = timestamp_sync(state->clocksync, timestamp, host_utime);
00314 
00315 #if 0
00316     if(state->last_timestamp) {
00317         printf("D  depth: %10.6f  img  : %10.6f  last : %10.6f  (%"PRId64")\n",
00318                (msg_utime - state->last_depth_timestamp) * 1e-6,
00319                (msg_utime - state->last_img_timestamp) * 1e-6,
00320                (msg_utime - state->last_timestamp) * 1e-6,
00321                msg_utime);
00322     }
00323     state->last_depth_timestamp = msg_utime;
00324     state->last_timestamp = msg_utime;
00325 #endif
00326 
00327     // don't capture a depth image until we have a camera image.  Assumes that
00328     // depth images always follow camera images in the data stream.
00329     if (!state->got_img)
00330         return;
00331     state->got_depth = 1;
00332 
00333     if (state->skip_depth) {
00334         state->msg.depth.timestamp = 0;
00335         state->msg.depth.width = 0;
00336         state->msg.depth.height = 0;
00337         state->msg.depth.depth_data_nbytes = 0;
00338         state->msg.depth.depth_data_format = KINECT_DEPTH_MSG_T_DEPTH_NONE;
00339         state->msg.depth.compression = KINECT_DEPTH_MSG_T_COMPRESSION_NONE;
00340         state->msg.depth.uncompressed_size = 0;
00341         return;
00342     }
00343 
00344     state->msg.depth.timestamp = msg_utime;
00345 
00346     freenect_frame_mode md = freenect_find_depth_mode(state->current_resolution, state->current_depth_format);
00347     state->msg.depth.depth_data_nbytes = md.bytes;
00348     state->msg.depth.depth_data_format = state->current_depth_format;
00349     if (state->current_depth_format == KINECT_DEPTH_MSG_T_DEPTH_10BIT_PACKED
00350         || state->current_depth_format == KINECT_DEPTH_MSG_T_DEPTH_11BIT_PACKED) {
00351         assert(state->msg.depth.depth_data_nbytes <= state->depth_unpack_buf_size);
00352         convert_packed_to_16bit(data, state->depth_unpack_buf, md.data_bits_per_pixel, 640 * 480); //todo size shouldn't be hardcoded
00353     }
00354     else {
00355         assert(state->msg.depth.depth_data_nbytes <= state->depth_unpack_buf_size);
00356         memcpy(state->depth_unpack_buf, data, state->msg.depth.depth_data_nbytes);
00357     }
00358 
00359     //  switch(state->current_depth_format) {
00360     //      case KINECT_DEPTH_MSG_T_DEPTH_11BIT:
00361     //     state->msg.depth.depth_data_nbytes = FREENECT_DEPTH_11BIT_SIZE;
00362     //     state->msg.depth.depth_data_format = KINECT_DEPTH_MSG_T_DEPTH_11BIT;
00363     //                      convert_packed_to_16bit(data, state->depth_unpack_buf, 11, FREENECT_FRAME_PIX);
00364     //     break;
00365     //   case KINECT_DEPTH_MSG_T_DEPTH_10BIT:
00366     //     state->msg.depth.depth_data_nbytes = FREENECT_DEPTH_10BIT_SIZE;
00367     //     state->msg.depth.depth_data_format = KINECT_DEPTH_MSG_T_DEPTH_10BIT;
00368     //                      convert_packed_to_16bit(data, state->depth_unpack_buf, 10, FREENECT_FRAME_PIX);
00369     //     break;
00370     //  #if 0
00371     //   case FREENECT_DEPTH_11BIT_PACKED:
00372     //     state->msg.depth.depth_data_nbytes = FREENECT_DEPTH_11BIT_PACKED_SIZE;
00373     //     state->msg.depth.depth_data_format = KINECT_DEPTH_MSG_T_DEPTH_11BIT_PACKED;
00374     //     break;
00375     //   case FREENECT_DEPTH_10BIT_PACKED:
00376     //     state->msg.depth.depth_data_nbytes = FREENECT_DEPTH_10BIT_PACKED_SIZE;
00377     //     state->msg.depth.depth_data_format = KINECT_DEPTH_MSG_T_DEPTH_10BIT_PACKED;
00378     //     break;
00379     //  #endif
00380     //   default:
00381     //     state->msg.depth.depth_data_nbytes = 0;
00382     //     state->msg.depth.depth_data_format = 0; // TODO spew warning
00383     //  }
00384 
00385     if (state->use_zlib) {
00386         int uncompressed_size = state->msg.depth.depth_data_nbytes;
00387         unsigned long compressed_size = state->depth_compress_buf_size;
00388         compress2(state->depth_compress_buf, &compressed_size, (void*) state->depth_unpack_buf, uncompressed_size,
00389                   Z_BEST_SPEED);
00390         state->msg.depth.depth_data_nbytes = (int) compressed_size;
00391         state->msg.depth.compression = KINECT_DEPTH_MSG_T_COMPRESSION_ZLIB;
00392         state->msg.depth.uncompressed_size = uncompressed_size;
00393     }
00394     else {
00395         assert(state->msg.depth.depth_data_nbytes <= state->depth_compress_buf_size);
00396         memcpy(state->depth_compress_buf, state->depth_unpack_buf, state->msg.depth.depth_data_nbytes);
00397         state->msg.depth.compression = KINECT_DEPTH_MSG_T_COMPRESSION_NONE;
00398         state->msg.depth.uncompressed_size = state->msg.depth.depth_data_nbytes;
00399     }
00400 }
00401 
00402 void
00403 image_cb(freenect_device *dev, void *data, uint32_t timestamp)
00404 {
00405     state_t* state = (state_t*) freenect_get_user(dev);
00406     int64_t host_utime = timestamp_now();
00407     int64_t msg_utime = timestamp_sync(state->clocksync, timestamp, host_utime);
00408 
00409 #if 0
00410     if(state->last_timestamp) {
00411         printf(" I depth: %10.6f  img  : %10.6f  last : %10.6f  (%"PRId64")\n",
00412                (msg_utime - state->last_depth_timestamp) * 1e-6,
00413                (msg_utime - state->last_img_timestamp) * 1e-6,
00414                (msg_utime - state->last_timestamp) * 1e-6,
00415                msg_utime);
00416     }
00417     state->last_img_timestamp = msg_utime;
00418     state->last_timestamp = msg_utime;
00419 #endif
00420 
00421     if (!rate_check(state->capture_rate)) {
00422         return;
00423     }
00424     state->got_img = 1;
00425 
00426     // if we don't actually care about images, then don't process it.
00427     if (state->skip_img) {
00428         state->msg.image.timestamp = 0;
00429         state->msg.image.width = 0;
00430         state->msg.image.height = 0;
00431         state->msg.image.image_data_nbytes = 0;
00432         state->msg.image.image_data_format = KINECT_IMAGE_MSG_T_VIDEO_NONE;
00433         return;
00434     }
00435 
00436     state->msg.image.timestamp = msg_utime;
00437 
00438     // Do we need to de-Bayer the image?
00439     if (state->current_image_format == KINECT_IMAGE_MSG_T_VIDEO_BAYER ||
00440         state->current_image_format == KINECT_IMAGE_MSG_T_VIDEO_RGB_JPEG) {
00441 
00442         cam_pixel_convert_bayer_to_8u_bgra(state->debayer_buf, state->debayer_buf_stride,
00443                                            640, 480, data, 640, CAM_PIXEL_FORMAT_BAYER_GRBG);
00444 
00445         // convert from bgra -> rgb and place the result back into the original
00446         // bayer buffer
00447         cam_pixel_convert_8u_bgra_to_8u_rgb((uint8_t*) data, 640 * 3, 640, 480,
00448                                             state->debayer_buf, state->debayer_buf_stride);
00449         state->msg.image.image_data_nbytes = 640 * 480 * 3;
00450         state->msg.image.image_data_format = KINECT_IMAGE_MSG_T_VIDEO_RGB;
00451     }
00452 
00453     // do we need to JPEG compress the image?
00454     if (state->current_image_format == KINECT_IMAGE_MSG_T_VIDEO_RGB_JPEG) {
00455         int compressed_size = state->image_buf_size;
00456 #if USE_JPEG_UTILS_POD
00457         int compression_status = jpeg_compress_8u_rgb (data, 640, 480, 640*3,
00458                                                        state->image_buf, &compressed_size, state->jpeg_quality);
00459 #else
00460         int compression_status = jpegijg_compress_8u_rgb(data, 640, 480, 640 * 3,
00461                                                          state->image_buf, &compressed_size, state->jpeg_quality);
00462 #endif
00463 
00464         if (0 != compression_status) {
00465             fprintf(stderr, "JPEG compression failed...\n");
00466         }
00467         state->msg.image.image_data_nbytes = compressed_size;
00468         state->msg.image.image_data_format = KINECT_IMAGE_MSG_T_VIDEO_RGB_JPEG;
00469 
00470     }
00471     else {
00472         assert(state->msg.image.image_data_nbytes <= state->image_buf_size);
00473         memcpy(state->image_buf, data, state->msg.image.image_data_nbytes);
00474     }
00475 }
00476 
00477 //int freenect_write_register(freenect_device *dev, uint16_t reg, uint16_t data);
00478 
00479 static void *
00480 freenect_threadfunc(void *user_data)
00481 {
00482     printf("starting kinect thread...\n");
00483     state_t* state = (state_t*) user_data;
00484 
00485     freenect_set_tilt_degs(state->f_dev, state->freenect_angle);
00486     freenect_set_led(state->f_dev, state->current_led);
00487     freenect_set_depth_callback(state->f_dev, depth_cb);
00488     freenect_set_video_callback(state->f_dev, image_cb);
00489     set_image_depth_formats(state);
00490     freenect_set_video_buffer(state->f_dev, state->image_data);
00491 
00492     //  if(state->capture_rate->target_hz <= 15) {
00493     //    int rval = (int)ceil(state->capture_rate->target_hz);
00494     //    int st = freenect_write_register(state->f_dev, 0xE, rval);
00495     //    printf("Decreasing RGB framerate to %d: %d\n", rval, st);
00496     //    st = freenect_write_register(state->f_dev, 0x14, rval);
00497     //    printf("Decreasing depth framerate to %d: %d\n", rval, st);
00498     //  }
00499 
00500     freenect_start_depth(state->f_dev);
00501     freenect_start_video(state->f_dev);
00502 
00503     while (!state->die && freenect_process_events(state->f_ctx) >= 0) {
00504 
00505         // ready to publish?
00506         if (state->got_img && state->got_depth) { // XXX could transmit sooner if we don't want to publish depth data
00507             populate_status(state, &state->msg, timestamp_now());
00508             kinect_frame_msg_t_publish(state->lcm, state->msg_channel, &state->msg);
00509 
00510             state->got_img = 0;
00511             state->got_depth = 0;
00512         }
00513 
00514 #if 0
00515         // do we need to change video formats?
00516         if (state->requested_image_format != state->current_image_format) {
00517             dbg("Changing Image format\n");
00518             freenect_stop_video(state->f_dev);
00519             freenect_set_video_format(state->f_dev, state->requested_image_format);
00520             freenect_start_video(state->f_dev);
00521             state->current_image_format = state->requested_image_format;
00522         }
00523 
00524         // do we need to change depth formats?
00525         if (state->requested_depth_format != state->current_depth_format) {
00526             dbg("Changing Depth format\n");
00527             freenect_stop_depth(state->f_dev);
00528             freenect_set_depth_format(state->f_dev, state->requested_depth_format);
00529             freenect_start_depth(state->f_dev);
00530             state->current_depth_format = state->requested_depth_format;
00531         }
00532 #endif
00533 
00534         if (rate_check(state->report_rate)) {
00535             printf("Capture rate: %5.2fHz (%6"PRId64")\n", state->capture_rate->current_hz, state->capture_rate->tick_count);
00536         }
00537     }
00538 
00539     printf("\nshutting down streams...\n");
00540 
00541     freenect_stop_depth(state->f_dev);
00542     freenect_stop_video(state->f_dev);
00543 
00544     freenect_close_device(state->f_dev);
00545     freenect_shutdown(state->f_ctx);
00546 
00547     printf("-- done!\n");
00548     return NULL;
00549 }
00550 
00551 //pthread - for publishing sensor status 
00552 static void *status_thread(void *user)
00553 {
00554     state_t *self = (state_t*) user;
00555 
00556     while(1){
00557         if(self->report_rate){
00558             kinect_sensor_status_t msg;
00559             msg.utime = timestamp_now();
00560             msg.sensor_name = "kinect"; //maybe use some indexing - to make it unique
00561             msg.rate = self->capture_rate->current_hz;
00562             
00563             msg.type = KINECT_SENSOR_STATUS_T_KINECT; //prob need to identify this more - if there are multiple kinects
00564 
00565             kinect_sensor_status_t_publish(self->lcm, "SENSOR_STATUS_KINECT", &msg);
00566         }
00567         sleep(1);
00568     }
00569     
00570     return 0;
00571 }
00572 
00573 static void usage(const char* progname)
00574 {
00575     fprintf(stderr, "Usage: %s [options]\n"
00576             "\n"
00577             "Options:\n"
00578             "  -r RATE   Throttle publishing to RATE Hz.\n"
00579             "  -d        Depth mode\n"
00580             "  -i        Image mode\n"
00581             "  -j        JPEG-compress RGB images\n"
00582             "  -q QUAL   JPEG compression quality (0-100, default 94)\n"
00583             "  -z        ZLib compress depth images\n"
00584             "  -l URL    Specify LCM URL\n"
00585             "  -h        This help message\n"
00586             "  -n dev    Number of the device to open\n"
00587             "  -c name   LCM channel\n",
00588             g_path_get_basename(progname));
00589 
00590     fprintf(stderr, "Image mode must be one of:\n"
00591             "  VIDEO_RGB             = 0\n"
00592             "  VIDEO_BAYER           = 1\n"
00593             "  VIDEO_IR_8BIT         = 2\n"
00594             "  VIDEO_IR_10BIT        = 3\n"
00595             "  VIDEO_IR_10BIT_PACKED = 4\n"
00596             "  VIDEO_YUV_RGB         = 5\n"
00597             "  VIDEO_YUV_RAW         = 6\n"
00598             "\n"
00599             "  VIDEO_DISABLED        = -1\n"
00600             );
00601 
00602     fprintf(stderr, "Depth mode must be one of:\n"
00603             "  DEPTH_11BIT        = 0\n"
00604             "  DEPTH_10BIT        = 1\n"
00605             "  DEPTH_11BIT_PACKED = 2\n"
00606             "  DEPTH_10BIT_PACKED = 3\n"
00607             "  DEPTH_REGISTERED   = 4\n"
00608             "  DEPTH_MM           = 5\n"
00609             "\n"
00610             "  DEPTH_DISABLED         =-1\n"
00611             );
00612     exit(1);
00613 }
00614 
00615 int main(int argc, char **argv)
00616 {
00617     state_t *state = (state_t*) calloc(1, sizeof(state_t));
00618 
00619     double target_rate = INFINITY;
00620 
00621     state->skip_img = 0;
00622     state->skip_depth = 0;
00623     state->throttle = 0;
00624     state->capture_rate = NULL;
00625 
00626     state->freenect_thread = NULL;
00627     state->die = 0;
00628 
00629     state->f_ctx = NULL;
00630     state->f_dev = NULL;
00631     state->freenect_angle = 0;
00632     state->freenect_led = 0;
00633 
00634     state->jpeg_quality = 94;
00635 
00636     // make these configurable - either/both from the command line and from outside LCM command
00637     state->requested_image_format = KINECT_IMAGE_MSG_T_VIDEO_BAYER;
00638     state->requested_depth_format = KINECT_DEPTH_MSG_T_DEPTH_11BIT;
00639     state->requested_led = LED_RED;
00640     state->current_image_format = state->requested_image_format;
00641     state->current_depth_format = state->requested_depth_format;
00642     state->current_led = state->requested_led;
00643     int user_device_number = 0;
00644     state->msg_channel = g_strdup("KINECT_FRAME");
00645 
00646     //todo this shouldn't be hardcoded
00647     state->current_resolution = FREENECT_RESOLUTION_MEDIUM;
00648 
00649     int c;
00650     char *lcm_url = NULL;
00651     // command line options - to throtle - to ignore image publish  
00652     while ((c = getopt(argc, argv, "hd:i:r:jq:zl:n:c:")) >= 0) {
00653         switch (c) {
00654         case 'i': //ignore images
00655             state->requested_image_format = atoi(optarg);
00656             break;
00657         case 'd':
00658             state->requested_depth_format = atoi(optarg);
00659             break;
00660         case 'j':
00661             state->requested_image_format = KINECT_IMAGE_MSG_T_VIDEO_RGB_JPEG;
00662             break;
00663         case 'q':
00664             state->jpeg_quality = atoi(optarg);
00665             if (state->jpeg_quality < 0 || state->jpeg_quality > 100)
00666                 usage(argv[0]);
00667             break;
00668         case 'n':
00669             user_device_number = atoi(optarg);
00670             printf("attempting to open device %i\n", user_device_number);
00671             break;
00672         case 'z':
00673             state->use_zlib = 1;
00674             printf("ZLib compressing depth data\n");
00675             break;
00676         case 'r':
00677             target_rate = strtod(optarg, NULL);
00678             printf("Target Rate is : %.3f Hz\n", target_rate);
00679             state->throttle = 1;
00680             break;
00681         case 'l':
00682             lcm_url = strdup(optarg);
00683             printf("Using LCM URL \"%s\"\n", lcm_url);
00684             break;
00685         case 'c':
00686             g_free(state->msg_channel);
00687             state->msg_channel = g_strdup(optarg);
00688             printf("Output on LCM channel: %s\n", state->msg_channel);
00689             break;
00690         case 'h':
00691         case '?':
00692             usage(argv[0]);
00693         }
00694     }
00695 
00696     const char * depthModeSting[] = {
00697         "DEPTH_11BIT",
00698         "DEPTH_10BIT",
00699         "DEPTH_11BIT_PACKED",
00700         "DEPTH_10BIT_PACKED",
00701         "DEPTH_REGISTERED",
00702         "DEPTH_MM",
00703     };
00704     switch (state->requested_depth_format) {
00705     case KINECT_DEPTH_MSG_T_DEPTH_11BIT:
00706     case KINECT_DEPTH_MSG_T_DEPTH_10BIT:
00707     case KINECT_DEPTH_MSG_T_DEPTH_11BIT_PACKED:
00708     case KINECT_DEPTH_MSG_T_DEPTH_10BIT_PACKED:
00709     case KINECT_DEPTH_MSG_T_DEPTH_REGISTERED:
00710     case KINECT_DEPTH_MSG_T_DEPTH_MM:
00711         dbg("Depth Mode is %s\n", depthModeSting[state->requested_depth_format]);
00712         break;
00713     case KINECT_DEPTH_MSG_T_DEPTH_NONE:
00714     case -1:
00715         dbg("Depth is disabled");
00716         state->requested_depth_format = KINECT_DEPTH_MSG_T_DEPTH_NONE;
00717         state->skip_depth = 1;
00718         break;
00719     default:
00720         dbg("Invalid depth format %d\n", state->requested_depth_format);
00721         usage(argv[0]);
00722         break;
00723     }
00724 
00725     const char * imageModeSting[] = {
00726         "VIDEO_RGB",
00727         "VIDEO_BAYER",
00728         "VIDEO_IR_8BIT",
00729         "VIDEO_IR_10BIT",
00730         "VIDEO_IR_10BIT_PACKED",
00731         "VIDEO_YUV_RGB",
00732         "VIDEO_YUV_RAW",
00733     };
00734 
00735     switch (state->requested_image_format) {
00736     case KINECT_IMAGE_MSG_T_VIDEO_RGB:
00737     case KINECT_IMAGE_MSG_T_VIDEO_BAYER:
00738     case KINECT_IMAGE_MSG_T_VIDEO_IR_8BIT:
00739     case KINECT_IMAGE_MSG_T_VIDEO_IR_10BIT:
00740     case KINECT_IMAGE_MSG_T_VIDEO_IR_10BIT_PACKED:
00741     case KINECT_IMAGE_MSG_T_VIDEO_YUV_RGB:
00742     case KINECT_IMAGE_MSG_T_VIDEO_YUV_RAW:
00743         dbg("Image Mode is %s\n", imageModeSting[state->requested_image_format]);
00744         break;
00745 
00746     case KINECT_IMAGE_MSG_T_VIDEO_RGB_JPEG:
00747         dbg("Jpeg Compressing RGB images\n");
00748         break;
00749     case KINECT_IMAGE_MSG_T_VIDEO_NONE:
00750     case -1:
00751         dbg("Image is disabled");
00752         state->requested_image_format = KINECT_IMAGE_MSG_T_VIDEO_NONE;
00753         state->skip_img = 1;
00754         break;
00755     default:
00756         dbg("Invalid image format %d\n", state->requested_image_format);
00757         usage(argv[0]);
00758         break;
00759     }
00760 
00761     /*
00762       int user_device_number = 0;
00763       if (argc > 1) {
00764       user_device_number = atoi(argv[1]);
00765       printf("attempting to open device %i\n", user_device_number);
00766       }
00767     */
00768 
00769     // throttling
00770     state->capture_rate = rate_new(target_rate);
00771 
00772     //todo the width and height should be computed from the desired resolution
00773 
00774     // allocate image and depth buffers
00775     state->image_data = (uint8_t*) malloc(640 * 480 * 4);
00776 
00777     // allocate more space for the image buffer, as we might use it for compressed data
00778     state->image_buf_size = 640 * 480 * 10;
00779     if (0 != posix_memalign((void**) &state->image_buf, 16, state->image_buf_size)) {
00780         fprintf(stderr, "Error allocating image buffer\n");
00781         return 1;
00782     }
00783     state->msg.image.image_data = state->image_buf;
00784     state->msg.image.width = 640; //TODO: this shouldn't be hardcoded
00785     state->msg.image.height = 480;
00786 
00787     // allocate a buffer for bayer de-mosaicing
00788     state->debayer_buf_size = 640 * 480 * 4;
00789     state->debayer_buf_stride = 640 * 4;
00790     if (0 != posix_memalign((void**) &state->debayer_buf, 16, state->debayer_buf_size)) {
00791         fprintf(stderr, "error allocating de-Bayer buffer\n");
00792         return 1;
00793     }
00794 
00795     // allocate space for unpacking depth data
00796     state->depth_unpack_buf_size = 640 * 480 * sizeof(uint16_t);
00797     state->depth_unpack_buf = (uint16_t*) malloc(state->depth_unpack_buf_size);
00798 
00799     // allocate space for zlib compressing depth data
00800     state->depth_compress_buf_size = 640 * 480 * sizeof(int16_t) * 4;
00801     state->depth_compress_buf = (uint8_t*) malloc(state->depth_compress_buf_size);
00802     state->msg.depth.depth_data = state->depth_compress_buf;
00803     state->msg.depth.width = 640;
00804     state->msg.depth.height = 480;
00805 
00806     state->got_img = 0;
00807     state->got_depth = 0;
00808 
00809     state->report_rate = rate_new(0.5);
00810 
00811     state->last_timestamp = 0;
00812 
00813     // initialize LCM
00814 
00815     state->lcm = lcm_create(lcm_url);
00816 
00817     if (!state->lcm) {
00818         fprintf(stderr, "Unable to initialize LCM\n");
00819         return 1;
00820     }
00821 
00822     // initialize the kinect device
00823     if (freenect_init(&state->f_ctx, NULL) < 0) {
00824         printf("freenect_init() failed\n");
00825         return 1;
00826     }
00827 
00828     freenect_set_log_level(state->f_ctx, FREENECT_LOG_INFO);
00829 
00830     int num_devices = freenect_num_devices(state->f_ctx);
00831     printf("Number of devices found: %d\n", num_devices);
00832 
00833     if (num_devices < 1)
00834         return 1;
00835 
00836     if (freenect_open_device(state->f_ctx, &state->f_dev, user_device_number) < 0) {
00837         printf("Could not open device\n");
00838         return 1;
00839     }
00840 
00841     freenect_set_user(state->f_dev, state);
00842 
00843     // setup passive time synchronization so we can guess the true image
00844     // acquisition times
00845     state->clocksync = timestamp_sync_init(100000000, 0xFFFFFFFFLL, 1.001);
00846 
00847     if (!g_thread_supported())
00848         g_thread_init(NULL);
00849 
00850     // subscribe to kinect command messages
00851     kinect_cmd_msg_t_subscribe(state->lcm, "KINECT_CMD", cmd_cb, state);
00852 
00853     GError *thread_err = NULL;
00854     state->freenect_thread = g_thread_create(freenect_threadfunc, state, TRUE, &thread_err);
00855     if (thread_err) {
00856         fprintf(stderr, "Error creating thread: %s\n", thread_err->message);
00857         return 1;
00858     }
00859 
00860     pthread_create(&state->work_thread, NULL, status_thread, state);
00861 
00862     while (!state->die) {
00863         lcm_handle(state->lcm);
00864     }
00865 
00866     timestamp_sync_free(state->clocksync);
00867     g_free(state->msg_channel);
00868     rate_destroy(state->capture_rate);
00869     free(state);
00870 
00871     return 0;
00872 }


libfovis
Author(s): Albert Huang, Maurice Fallon
autogenerated on Thu Jun 6 2019 20:16:12