camera.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/CompressedImage.h"
00009 #include "sensor_msgs/image_encodings.h"
00010 #include "sensor_msgs/CameraInfo.h"
00011 #include "camera_info_manager/camera_info_manager.h"
00012 #include "image_transport/image_transport.h"
00013 
00014 #include "uvc_camera/camera.h"
00015 
00016 using namespace sensor_msgs;
00017 
00018 namespace uvc_camera {
00019 
00020 Camera::Camera(ros::NodeHandle _comm_nh, ros::NodeHandle _param_nh) :
00021       node(_comm_nh), pnode(_param_nh), it(_comm_nh),
00022       info_mgr(_comm_nh, "camera"), cam(0) {
00023 
00024       /* default config values */
00025       width = 640;
00026       height = 480;
00027       fps = 10;
00028       skip_frames = 0;
00029       frames_to_skip = 0;
00030       device = "/dev/video0";
00031       frame = "camera";
00032       rotate = false;
00033       format = "rgb";
00034 
00035       /* set up information manager */
00036       std::string url, camera_name;
00037       pnode.getParam("camera_info_url", url);
00038       pnode.param<std::string>("camera_name", camera_name, "camera");
00039 
00040       info_mgr.setCameraName(camera_name);
00041       info_mgr.loadCameraInfo(url);
00042 
00043       /* pull other configuration */
00044       pnode.getParam("device", device);
00045 
00046       pnode.getParam("fps", fps);
00047       pnode.getParam("skip_frames", skip_frames);
00048 
00049       pnode.getParam("width", width);
00050       pnode.getParam("height", height);
00051 
00052       pnode.getParam("frame_id", frame);
00053 
00054       pnode.getParam("format", format);
00055 
00056       /* advertise image streams and info streams */
00057       if (format != "jpeg")
00058         pub = it.advertise("image_raw", 1);
00059       else
00060         pubjpeg = node.advertise<CompressedImage>("image_raw/compressed", 1);
00061 
00062       info_pub = node.advertise<CameraInfo>("camera_info", 1);
00063 
00064       /* initialize the cameras */
00065       uvc_cam::Cam::mode_t mode = uvc_cam::Cam::MODE_RGB;
00066       if (format == "jpeg") 
00067         mode = uvc_cam::Cam::MODE_MJPG;      
00068       cam = new uvc_cam::Cam(device.c_str(), mode, width, height, fps);
00069       cam->set_motion_thresholds(100, -1);
00070 
00071       bool auto_focus;
00072       if (pnode.getParam("auto_focus", auto_focus)) {
00073         cam->set_v4l2_control(V4L2_CID_FOCUS_AUTO, auto_focus, "auto_focus");
00074       }
00075 
00076       int focus_absolute;
00077       if (pnode.getParam("focus_absolute", focus_absolute)) {
00078         cam->set_v4l2_control(V4L2_CID_FOCUS_ABSOLUTE, focus_absolute, "focus_absolute");
00079       }
00080 
00081       bool auto_exposure;
00082       if (pnode.getParam("auto_exposure", auto_exposure)) {
00083         int val;
00084         if (auto_exposure) {
00085           val = V4L2_EXPOSURE_AUTO;
00086         } else {
00087           val = V4L2_EXPOSURE_MANUAL;
00088         }
00089         cam->set_v4l2_control(V4L2_CID_EXPOSURE_AUTO, val, "auto_exposure");
00090       }
00091 
00092       int exposure_auto_priority;
00093       if (pnode.getParam("exposure_auto_priority", exposure_auto_priority)) {
00094         cam->set_v4l2_control(V4L2_CID_EXPOSURE_AUTO_PRIORITY, exposure_auto_priority, "exposure_auto_priority");
00095       } 
00096 
00097       int exposure_absolute;
00098       if (pnode.getParam("exposure_absolute", exposure_absolute)) {
00099         cam->set_v4l2_control(V4L2_CID_EXPOSURE_ABSOLUTE, exposure_absolute, "exposure_absolute");
00100       }
00101 
00102       int exposure;
00103       if (pnode.getParam("exposure", exposure)) {
00104         cam->set_v4l2_control(V4L2_CID_EXPOSURE, exposure, "exposure");
00105       }
00106       
00107       int brightness;
00108       if (pnode.getParam("brightness", brightness)) {
00109         cam->set_v4l2_control(V4L2_CID_BRIGHTNESS, brightness, "brightness");
00110       }
00111 
00112       int power_line_frequency;
00113       if (pnode.getParam("power_line_frequency", power_line_frequency)) {
00114         int val;
00115         if (power_line_frequency == 0) {
00116           val = V4L2_CID_POWER_LINE_FREQUENCY_DISABLED;
00117         } else if (power_line_frequency == 50) {
00118           val = V4L2_CID_POWER_LINE_FREQUENCY_50HZ;
00119         } else if (power_line_frequency == 60) {
00120           val = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
00121         } else {
00122           printf("power_line_frequency=%d not supported. Using auto.\n", power_line_frequency);
00123           val = V4L2_CID_POWER_LINE_FREQUENCY_AUTO;
00124         }
00125         cam->set_v4l2_control(V4L2_CID_POWER_LINE_FREQUENCY, val, "power_line_frequency");
00126       }
00127 
00128       int contrast;
00129       if (pnode.getParam("contrast", contrast)) {
00130         cam->set_v4l2_control(V4L2_CID_CONTRAST, contrast, "contrast");  
00131       }
00132 
00133       int saturation;
00134       if (pnode.getParam("saturation", saturation)) {
00135         cam->set_v4l2_control(V4L2_CID_SATURATION, saturation, "saturation"); 
00136       }
00137 
00138       int hue;
00139       if (pnode.getParam("hue", hue)) {
00140         cam->set_v4l2_control(V4L2_CID_HUE, hue, "hue"); 
00141       }
00142 
00143       bool auto_white_balance;
00144       if (pnode.getParam("auto_white_balance", auto_white_balance)) {
00145         cam->set_v4l2_control(V4L2_CID_AUTO_WHITE_BALANCE, auto_white_balance, "auto_white_balance");
00146       }
00147 
00148       int white_balance_tmp;
00149       if (pnode.getParam("white_balance_temperature", white_balance_tmp)) {   
00150         cam->set_v4l2_control(V4L2_CID_WHITE_BALANCE_TEMPERATURE, white_balance_tmp, "white_balance_temperature"); 
00151       }
00152       
00153       int gamma;
00154       if (pnode.getParam("gamma", gamma)) {
00155         cam->set_v4l2_control(V4L2_CID_GAMMA, gamma, "gamma");
00156       }
00157 
00158       int sharpness;
00159       if (pnode.getParam("sharpness", sharpness)) {
00160         cam->set_v4l2_control(V4L2_CID_SHARPNESS, sharpness, "sharpness");
00161       }
00162 
00163       int backlight_comp;
00164       if (pnode.getParam("backlight_compensation", backlight_comp)) {
00165         cam->set_v4l2_control(V4L2_CID_BACKLIGHT_COMPENSATION, backlight_comp, "backlight_compensation");
00166       }
00167 
00168       bool auto_gain;
00169       if (pnode.getParam("auto_gain", auto_gain)) {
00170         cam->set_v4l2_control(V4L2_CID_AUTOGAIN, auto_gain, "auto_gain");
00171       }
00172 
00173       int gain;
00174       if (pnode.getParam("gain", gain)) {
00175         cam->set_v4l2_control(V4L2_CID_GAIN, gain, "gain");
00176       }
00177 
00178       bool h_flip;
00179       if (pnode.getParam("horizontal_flip", h_flip)) {
00180         cam->set_v4l2_control(V4L2_CID_HFLIP, h_flip, "horizontal_flip");
00181       }
00182 
00183       bool v_flip;
00184       if (pnode.getParam("vertical_flip", v_flip)) {
00185         cam->set_v4l2_control(V4L2_CID_VFLIP, v_flip, "vertical_flip");
00186       }
00187 
00188       // TODO: 
00189       // - zoom absolute, zoom relative and zoom continuous controls
00190       // - add generic parameter list:
00191       //   [(id0, val0, name0), (id1, val1, name1), ...
00192 
00193       /* and turn on the streamer */
00194       ok = true;
00195       image_thread = boost::thread(boost::bind(&Camera::feedImages, this));
00196     }
00197 
00198     void Camera::sendInfo(ImagePtr &image, ros::Time time) {
00199       CameraInfoPtr info(new CameraInfo(info_mgr.getCameraInfo()));
00200 
00201       /* Throw out any CamInfo that's not calibrated to this camera mode */
00202       if (info->K[0] != 0.0 &&
00203            (image->width != info->width
00204               || image->height != info->height)) {
00205         info.reset(new CameraInfo());
00206       }
00207 
00208       /* If we don't have a calibration, set the image dimensions */
00209       if (info->K[0] == 0.0) {
00210         info->width = image->width;
00211         info->height = image->height;
00212       }
00213 
00214       info->header.stamp = time;
00215       info->header.frame_id = frame;
00216 
00217       info_pub.publish(info);
00218     }
00219 
00220     void Camera::sendInfoJpeg(ros::Time time) {
00221       CameraInfoPtr info(new CameraInfo(info_mgr.getCameraInfo()));
00222       info->header.stamp = time;
00223       info->header.frame_id = frame;
00224 
00225       info_pub.publish(info);
00226     }
00227 
00228     void Camera::feedImages() {
00229       unsigned int pair_id = 0;
00230       while (ok) {
00231         unsigned char *img_frame = NULL;
00232         uint32_t bytes_used;
00233 
00234         ros::Time capture_time = ros::Time::now();
00235 
00236         int idx = cam->grab(&img_frame, bytes_used);
00237 
00238         /* Read in every frame the camera generates, but only send each
00239          * (skip_frames + 1)th frame. It's set up this way just because
00240          * this is based on Stereo...
00241          */
00242         if (skip_frames == 0 || frames_to_skip == 0) {
00243           if (img_frame && format != "jpeg") {
00244              ImagePtr image(new Image);
00245 
00246              image->height = height;
00247              image->width = width;
00248              image->step = 3 * width;
00249              image->encoding = image_encodings::RGB8;
00250 
00251              image->header.stamp = capture_time;
00252              image->header.seq = pair_id;
00253 
00254              image->header.frame_id = frame;
00255 
00256              image->data.resize(image->step * image->height);
00257 
00258              memcpy(&image->data[0], img_frame, width*height * 3);
00259 
00260              pub.publish(image);
00261 
00262              sendInfo(image, capture_time);
00263 
00264              ++pair_id;
00265           } else if (img_frame && format == "jpeg") {
00266              CompressedImagePtr image(new CompressedImage);
00267 
00268              image->header.stamp = capture_time;
00269              image->header.seq = pair_id;
00270 
00271              image->header.frame_id = frame;
00272 
00273              image->data.resize(bytes_used);
00274 
00275              memcpy(&image->data[0], img_frame, bytes_used);
00276 
00277              pubjpeg.publish(image);
00278 
00279              sendInfoJpeg(capture_time);
00280 
00281              ++pair_id;
00282           }
00283 
00284           frames_to_skip = skip_frames;
00285         } else {
00286           frames_to_skip--;
00287         }
00288 
00289         if (img_frame) cam->release(idx);
00290       }
00291     }
00292 
00293     Camera::~Camera() {
00294       ok = false;
00295       image_thread.join();
00296       if (cam) delete cam;
00297     }
00298 
00299 
00300 };
00301 


uvc_camera
Author(s): Ken Tossell
autogenerated on Thu Jun 15 2017 02:29:40