stereo.cpp
Go to the documentation of this file.
00001 #include <boost/thread.hpp>
00002 
00003 #include <ros/ros.h>
00004 #include <ros/time.h>
00005 
00006 #include "uvc_cam/uvc_cam.h"
00007 #include "sensor_msgs/Image.h"
00008 #include "sensor_msgs/image_encodings.h"
00009 #include "sensor_msgs/CameraInfo.h"
00010 #include "camera_info_manager/camera_info_manager.h"
00011 #include "image_transport/image_transport.h"
00012 
00013 #include "uvc_camera/stereocamera.h"
00014 
00015 using namespace sensor_msgs;
00016 
00017 /* Rotate an 8-bit, 3-channel image by 180 degrees. */
00018 static inline void rotate(unsigned char *dst_chr, unsigned char *src_chr, int pixels) {
00019   struct pixel_t {
00020     unsigned char r, g, b;
00021   };
00022 
00023   struct pixel_t *src = (pixel_t *) src_chr;
00024   struct pixel_t *dst = &(((pixel_t *) dst_chr)[pixels - 1]);
00025 
00026   for (int i = pixels; i != 0; --i) {
00027     *dst = *src;
00028     src++;
00029     dst--;
00030   }
00031 }
00032 
00033 namespace uvc_camera {
00034 
00035 StereoCamera::StereoCamera(ros::NodeHandle comm_nh, ros::NodeHandle param_nh) :
00036   node(comm_nh), pnode(param_nh), it(comm_nh),
00037   left_info_mgr(ros::NodeHandle(comm_nh, "left"), "left_camera"),
00038   right_info_mgr(ros::NodeHandle(comm_nh, "right"), "right_camera") {
00039 
00040   /* default config values */
00041   width = 640;
00042   height = 480;
00043   fps = 10;
00044   skip_frames = 0;
00045   frames_to_skip = 0;
00046   left_device = "/dev/video0";
00047   right_device = "/dev/video1";
00048   frame = "camera";
00049   rotate_left = false;
00050   rotate_right = false;
00051 
00052   /* set up information managers */
00053   std::string left_url, right_url;
00054 
00055   pnode.getParam("left/camera_info_url", left_url);
00056   pnode.getParam("right/camera_info_url", right_url);
00057 
00058   left_info_mgr.loadCameraInfo(left_url);
00059   right_info_mgr.loadCameraInfo(right_url);
00060 
00061   /* pull other configuration */
00062   pnode.getParam("left/device", left_device);
00063   pnode.getParam("right/device", right_device);
00064 
00065   pnode.getParam("fps", fps);
00066   pnode.getParam("skip_frames", skip_frames);
00067 
00068   pnode.getParam("left/rotate", rotate_left);
00069   pnode.getParam("right/rotate", rotate_right);
00070 
00071   pnode.getParam("width", width);
00072   pnode.getParam("height", height);
00073 
00074   pnode.getParam("frame_id", frame);
00075 
00076   /* advertise image streams and info streams */
00077   left_pub = it.advertise("left/image_raw", 1);
00078   right_pub = it.advertise("right/image_raw", 1);
00079 
00080   left_info_pub = node.advertise<CameraInfo>("left/camera_info", 1);
00081   right_info_pub = node.advertise<CameraInfo>("right/camera_info", 1);
00082 
00083   /* initialize the cameras */
00084   cam_left =
00085       new uvc_cam::Cam(left_device.c_str(), uvc_cam::Cam::MODE_RGB,
00086                        width, height, fps);
00087   cam_left->set_motion_thresholds(100, -1);
00088   cam_right =
00089       new uvc_cam::Cam(right_device.c_str(), uvc_cam::Cam::MODE_RGB,
00090                        width, height, fps);
00091   cam_right->set_motion_thresholds(100, -1);
00092 
00093   /* and turn on the streamer */
00094   ok = true;
00095   image_thread = boost::thread(boost::bind(&StereoCamera::feedImages, this));
00096 }
00097 
00098 void StereoCamera::sendInfo(ros::Time time) {
00099   CameraInfoPtr info_left(new CameraInfo(left_info_mgr.getCameraInfo()));
00100   CameraInfoPtr info_right(new CameraInfo(right_info_mgr.getCameraInfo()));
00101 
00102   info_left->header.stamp = time;
00103   info_right->header.stamp = time;
00104   info_left->header.frame_id = frame;
00105   info_right->header.frame_id = frame;
00106 
00107   left_info_pub.publish(info_left);
00108   right_info_pub.publish(info_right);
00109 }
00110 
00111 
00112 void StereoCamera::feedImages() {
00113   unsigned int pair_id = 0;
00114   while (ok) {
00115     unsigned char *frame_left = NULL, *frame_right = NULL;
00116     uint32_t bytes_used_left, bytes_used_right;
00117 
00118     ros::Time capture_time = ros::Time::now();
00119 
00120     int left_idx = cam_left->grab(&frame_left, bytes_used_left);
00121     int right_idx = cam_right->grab(&frame_right, bytes_used_right);
00122 
00123     /* Read in every frame the camera generates, but only send each
00124      * (skip_frames + 1)th frame. This reduces effective frame
00125      * rate, processing time and network usage while keeping the
00126      * images synchronized within the true framerate.
00127      */
00128     if (skip_frames == 0 || frames_to_skip == 0) {
00129       if (frame_left && frame_right) {
00130         ImagePtr image_left(new Image);
00131         ImagePtr image_right(new Image);
00132 
00133         image_left->height = height;
00134         image_left->width = width;
00135         image_left->step = 3 * width;
00136         image_left->encoding = image_encodings::RGB8;
00137         image_left->header.stamp = capture_time;
00138         image_left->header.seq = pair_id;
00139 
00140         image_right->height = height;
00141         image_right->width = width;
00142         image_right->step = 3 * width;
00143         image_right->encoding = image_encodings::RGB8;
00144         image_right->header.stamp = capture_time;
00145         image_right->header.seq = pair_id;
00146 
00147         image_left->header.frame_id = frame;
00148         image_right->header.frame_id = frame;
00149 
00150         image_left->data.resize(image_left->step * image_left->height);
00151         image_right->data.resize(image_right->step * image_right->height);
00152 
00153         if (rotate_left)
00154           rotate(&image_left->data[0], frame_left, width * height);
00155         else
00156           memcpy(&image_left->data[0], frame_left, width * height * 3);
00157 
00158         if (rotate_right)
00159           rotate(&image_right->data[0], frame_right, width * height);
00160         else
00161           memcpy(&image_right->data[0], frame_right, width * height * 3);
00162 
00163         left_pub.publish(image_left);
00164         right_pub.publish(image_right);
00165 
00166         sendInfo(capture_time);
00167 
00168         ++pair_id;
00169       }
00170 
00171       frames_to_skip = skip_frames;
00172     } else {
00173       frames_to_skip--;
00174     }
00175 
00176     if (frame_left)
00177       cam_left->release(left_idx);
00178     if (frame_right)
00179       cam_right->release(right_idx);
00180   }
00181 }
00182 
00183 StereoCamera::~StereoCamera() {
00184   ok = false;
00185   image_thread.join();
00186   if (cam_left)
00187     delete cam_left;
00188   if (cam_right)
00189     delete cam_right;
00190 }
00191 
00192 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


uvc_camera
Author(s): Ken Tossell/ktossell@umd.edu
autogenerated on Sat Jul 27 2013 22:46:52