37 #include <sensor_msgs/Image.h> 38 #include <std_msgs/Header.h> 40 #include <dynamic_reconfigure/server.h> 41 #include <libuvc/libuvc.h> 42 #include <astra_camera/GetDeviceType.h> 43 #include <astra_camera/GetCameraInfo.h> 46 #define libuvc_VERSION (libuvc_VERSION_MAJOR * 10000 \ 47 + libuvc_VERSION_MINOR * 100 \ 48 + libuvc_VERSION_PATCH) 53 : nh_(nh), priv_nh_(priv_nh),
55 ctx_(NULL), dev_(NULL), devh_(NULL), rgb_frame_(NULL),
57 config_server_(mutex_, priv_nh_),
58 config_changed_(false),
75 for (slash_end = 0; slash_end <
ns.length(); slash_end++)
77 if (
ns[slash_end] !=
'/')
97 uvc_error_t err = uvc_get_exposure_abs(
devh_, &expo, UVC_GET_CUR);
99 return (err == UVC_SUCCESS);
104 if (req.exposure == 0)
106 uvc_set_ae_mode(
devh_, 2);
109 uvc_set_ae_mode(
devh_, 1);
110 if (req.exposure > 330)
112 ROS_ERROR(
"Please set exposure lower than 330");
115 uvc_error_t err = uvc_set_exposure_abs(
devh_, req.exposure);
116 return (err == UVC_SUCCESS);
122 uvc_error_t err = uvc_get_gain(
devh_, &gain, UVC_GET_CUR);
124 return (err == UVC_SUCCESS);
129 uvc_error_t err = uvc_set_gain(
devh_, req.gain);
130 return (err == UVC_SUCCESS);
136 uvc_error_t err = uvc_get_white_balance_temperature(
devh_, &white_balance, UVC_GET_CUR);
137 res.white_balance = white_balance;
138 return (err == UVC_SUCCESS);
143 if (req.white_balance == 0)
145 uvc_set_white_balance_temperature_auto(
devh_, 1);
148 uvc_set_white_balance_temperature_auto(
devh_, 0);
149 uvc_error_t err = uvc_set_white_balance_temperature(
devh_, req.white_balance);
150 return (err == UVC_SUCCESS);
158 err = uvc_init(&
ctx_, NULL);
160 if (err != UVC_SUCCESS) {
161 uvc_perror(err,
"ERROR: uvc_init");
173 boost::recursive_mutex::scoped_lock(
mutex_);
189 boost::recursive_mutex::scoped_lock(
mutex_);
200 if (new_config.camera_info_url !=
config_.camera_info_url)
204 #define PARAM_INT(name, fn, value) if (new_config.name != config_.name) { \ 206 if (uvc_set_##fn(devh_, val)) { \ 207 ROS_WARN("Unable to set " #name " to %d", val); \ 208 new_config.name = config_.name; \ 212 PARAM_INT(scanning_mode, scanning_mode, new_config.scanning_mode);
213 PARAM_INT(auto_exposure, ae_mode, 1 << new_config.auto_exposure);
214 PARAM_INT(auto_exposure_priority, ae_priority, new_config.auto_exposure_priority);
215 PARAM_INT(exposure_absolute, exposure_abs, new_config.exposure_absolute * 10000);
216 PARAM_INT(auto_focus, focus_auto, new_config.auto_focus ? 1 : 0);
217 PARAM_INT(focus_absolute, focus_abs, new_config.focus_absolute);
218 #if libuvc_VERSION > 00005 220 PARAM_INT(iris_absolute, iris_abs, new_config.iris_absolute);
221 PARAM_INT(brightness, brightness, new_config.brightness);
225 if (new_config.pan_absolute !=
config_.pan_absolute || new_config.tilt_absolute !=
config_.tilt_absolute) {
226 if (uvc_set_pantilt_abs(
devh_, new_config.pan_absolute, new_config.tilt_absolute)) {
227 ROS_WARN(
"Unable to set pantilt to %d, %d", new_config.pan_absolute, new_config.tilt_absolute);
228 new_config.pan_absolute =
config_.pan_absolute;
229 new_config.tilt_absolute =
config_.tilt_absolute;
251 ros::Time timestamp =
ros::Time(frame->capture_time.tv_sec, frame->capture_time.tv_usec);
256 boost::recursive_mutex::scoped_lock(
mutex_);
261 sensor_msgs::Image::Ptr image(
new sensor_msgs::Image());
263 image->height =
config_.height;
264 image->step = image->width * 3;
265 image->data.resize(image->step * image->height);
267 if (frame->frame_format == UVC_FRAME_FORMAT_BGR){
268 image->encoding =
"bgr8";
269 memcpy(&(image->data[0]), frame->data, frame->data_bytes);
270 }
else if (frame->frame_format == UVC_FRAME_FORMAT_RGB){
271 image->encoding =
"rgb8";
272 memcpy(&(image->data[0]), frame->data, frame->data_bytes);
273 }
else if (frame->frame_format == UVC_FRAME_FORMAT_UYVY) {
274 image->encoding =
"yuv422";
275 memcpy(&(image->data[0]), frame->data, frame->data_bytes);
276 }
else if (frame->frame_format == UVC_FRAME_FORMAT_YUYV) {
278 uvc_error_t conv_ret = uvc_yuyv2bgr(frame,
rgb_frame_);
279 if (conv_ret != UVC_SUCCESS) {
280 uvc_perror(conv_ret,
"Couldn't convert frame to RGB");
283 image->encoding =
"bgr8";
285 #if libuvc_VERSION > 00005 286 }
else if (frame->frame_format == UVC_FRAME_FORMAT_MJPEG) {
289 uvc_error_t conv_ret = uvc_mjpeg2rgb(frame,
rgb_frame_);
290 if (conv_ret != UVC_SUCCESS) {
291 uvc_perror(conv_ret,
"Couldn't convert frame to RGB");
294 image->encoding =
"rgb8";
298 uvc_error_t conv_ret = uvc_any2bgr(frame,
rgb_frame_);
299 if (conv_ret != UVC_SUCCESS) {
300 uvc_perror(conv_ret,
"Couldn't convert frame to RGB");
303 image->encoding =
"bgr8";
307 astra_camera::GetDeviceType device_type_srv;
308 astra_camera::GetCameraInfo camera_info_srv;
360 cinfo->height = image->height;
361 cinfo->width = image->width;
362 cinfo->distortion_model =
camera_info_.distortion_model;
363 cinfo->D.resize(5, 0.0);
364 cinfo->D[4] = 0.0000000001;
369 for (
int i = 0; i < 9; i++)
376 for (
int i = 0; i < 12; i++)
381 image->header.frame_id =
ns_no_slash +
"_rgb_optical_frame";
382 cinfo->header.frame_id =
ns_no_slash +
"_rgb_optical_frame";
386 image->header.frame_id =
config_.frame_id;
387 cinfo->header.frame_id =
config_.frame_id;
389 image->header.stamp = timestamp;
390 cinfo->header.stamp = timestamp;
408 enum uvc_status_class status_class,
411 enum uvc_status_attribute status_attribute,
412 void *data,
size_t data_len) {
413 boost::recursive_mutex::scoped_lock(
mutex_);
415 printf(
"Controls callback. class: %d, event: %d, selector: %d, attr: %d, data_len: %zu\n",
416 status_class, event, selector, status_attribute, data_len);
418 if (status_attribute == UVC_STATUS_ATTRIBUTE_VALUE_CHANGE) {
419 switch (status_class) {
420 case UVC_STATUS_CLASS_CONTROL_CAMERA: {
422 case UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
424 uint32_t exposure_int = ((data_char[0]) | (data_char[1] << 8) |
425 (data_char[2] << 16) | (data_char[3] << 24));
426 config_.exposure_absolute = exposure_int * 0.0001;
432 case UVC_STATUS_CLASS_CONTROL_PROCESSING: {
434 case UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
436 config_.white_balance_temperature =
437 data_char[0] | (data_char[1] << 8);
450 enum uvc_status_class status_class,
453 enum uvc_status_attribute status_attribute,
454 void *data,
size_t data_len,
459 status_attribute, data, data_len);
463 if(vmode ==
"uncompressed") {
464 return UVC_COLOR_FORMAT_UNCOMPRESSED;
465 }
else if (vmode ==
"compressed") {
466 return UVC_COLOR_FORMAT_COMPRESSED;
467 }
else if (vmode ==
"yuyv") {
468 return UVC_COLOR_FORMAT_YUYV;
469 }
else if (vmode ==
"uyvy") {
470 return UVC_COLOR_FORMAT_UYVY;
471 }
else if (vmode ==
"rgb") {
472 return UVC_COLOR_FORMAT_RGB;
473 }
else if (vmode ==
"bgr") {
474 return UVC_COLOR_FORMAT_BGR;
475 }
else if (vmode ==
"mjpeg") {
476 return UVC_COLOR_FORMAT_MJPEG;
477 }
else if (vmode ==
"gray8") {
478 return UVC_COLOR_FORMAT_GRAY8;
482 return UVC_COLOR_FORMAT_UNCOMPRESSED;
489 int vendor_id = strtol(new_config.vendor.c_str(), NULL, 0);
490 int product_id = strtol(new_config.product.c_str(), NULL, 0);
492 ROS_INFO(
"Opening camera with vendor=0x%x, product=0x%x, serial=\"%s\", index=%d",
493 vendor_id, product_id, new_config.serial.c_str(), new_config.index);
499 #if libuvc_VERSION > 00005 500 uvc_error_t find_err = uvc_find_devices(
504 new_config.serial.empty() ? NULL : new_config.serial.c_str());
506 if (find_err != UVC_SUCCESS) {
507 uvc_perror(find_err,
"uvc_find_device");
514 while (devs[dev_idx] != NULL) {
515 if(dev_idx == new_config.index) {
516 dev_ = devs[dev_idx];
519 uvc_unref_device(devs[dev_idx]);
526 ROS_ERROR(
"Unable to find device at index %d", new_config.index);
530 uvc_error_t find_err = uvc_find_device(
534 new_config.serial.empty() ? NULL : new_config.serial.c_str());
536 if (find_err != UVC_SUCCESS) {
537 uvc_perror(find_err,
"uvc_find_device");
542 uvc_error_t open_err = uvc_open(
dev_, &
devh_);
544 if (open_err != UVC_SUCCESS) {
546 case UVC_ERROR_ACCESS:
548 ROS_ERROR(
"Permission denied opening /dev/bus/usb/%03d/%03d",
549 uvc_get_bus_number(
dev_), uvc_get_device_address(
dev_));
551 ROS_ERROR(
"Permission denied opening device %d on bus %d",
552 uvc_get_device_address(
dev_), uvc_get_bus_number(
dev_));
557 ROS_ERROR(
"Can't open /dev/bus/usb/%03d/%03d: %s (%d)",
558 uvc_get_bus_number(
dev_), uvc_get_device_address(
dev_),
559 uvc_strerror(open_err), open_err);
561 ROS_ERROR(
"Can't open device %d on bus %d: %s (%d)",
562 uvc_get_device_address(
dev_), uvc_get_bus_number(
dev_),
563 uvc_strerror(open_err), open_err);
568 uvc_unref_device(
dev_);
574 uvc_stream_ctrl_t ctrl;
575 uvc_error_t mode_err = uvc_get_stream_ctrl_format_size(
578 new_config.width, new_config.height,
579 new_config.frame_rate);
581 if (mode_err != UVC_SUCCESS) {
582 uvc_perror(mode_err,
"uvc_get_stream_ctrl_format_size");
584 uvc_unref_device(
dev_);
585 ROS_ERROR(
"check video_mode/width/height/frame_rate are available");
586 uvc_print_diag(
devh_, NULL);
592 if (stream_err != UVC_SUCCESS) {
593 uvc_perror(stream_err,
"uvc_start_streaming");
595 uvc_unref_device(
dev_);
602 rgb_frame_ = uvc_allocate_frame(new_config.width * new_config.height * 3);
614 uvc_unref_device(
dev_);
boost::recursive_mutex mutex_
ros::ServiceServer set_uvc_exposure_server
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
static void ImageCallbackAdapter(uvc_frame_t *frame, void *ptr)
enum uvc_frame_format GetVideoMode(std::string vmode)
void publish(const sensor_msgs::Image &image, const sensor_msgs::CameraInfo &info) const
bool getUVCExposureCb(astra_camera::GetUVCExposureRequest &req, astra_camera::GetUVCExposureResponse &res)
sensor_msgs::CameraInfo getCameraInfo(void)
ros::ServiceServer get_uvc_gain_server
bool setUVCGainCb(astra_camera::SetUVCGainRequest &req, astra_camera::SetUVCGainResponse &res)
ros::ServiceServer get_uvc_white_balance_server
bool loadCameraInfo(const std::string &url)
bool setUVCExposureCb(astra_camera::SetUVCExposureRequest &req, astra_camera::SetUVCExposureResponse &res)
bool call(MReq &req, MRes &res)
static void AutoControlsCallbackAdapter(enum uvc_status_class status_class, int event, int selector, enum uvc_status_attribute status_attribute, void *data, size_t data_len, void *ptr)
ros::ServiceClient camera_info_client
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
image_transport::ImageTransport it_
ros::ServiceServer set_uvc_white_balance_server
sensor_msgs::CameraInfo camera_info_
dynamic_reconfigure::Server< UVCCameraConfig > config_server_
ros::ServiceServer get_uvc_exposure_server
bool astraWithUVC(OB_DEVICE_NO id)
void ReconfigureCallback(UVCCameraConfig &config, uint32_t level)
CameraPublisher advertiseCamera(const std::string &base_topic, uint32_t queue_size, bool latch=false)
void ImageCallback(uvc_frame_t *frame)
ROSCPP_DECL const std::string & getNamespace()
bool getUVCGainCb(astra_camera::GetUVCGainRequest &req, astra_camera::GetUVCGainResponse &res)
bool setUVCWhiteBalanceCb(astra_camera::SetUVCWhiteBalanceRequest &req, astra_camera::SetUVCWhiteBalanceResponse &res)
#define PARAM_INT(name, fn, value)
ros::ServiceClient device_type_client
#define ROS_WARN_STREAM(args)
bool getUVCWhiteBalanceCb(astra_camera::GetUVCWhiteBalanceRequest &req, astra_camera::GetUVCWhiteBalanceResponse &res)
void OpenCamera(UVCCameraConfig &new_config)
image_transport::CameraPublisher cam_pub_
camera_info_manager::CameraInfoManager cinfo_manager_
void AutoControlsCallback(enum uvc_status_class status_class, int event, int selector, enum uvc_status_attribute status_attribute, void *data, size_t data_len)
ros::ServiceServer set_uvc_gain_server
static const int kReconfigureClose
CameraDriver(ros::NodeHandle nh, ros::NodeHandle priv_nh)
#define ROS_ERROR_STREAM(args)
OB_DEVICE_NO device_type_no_
uvc_device_handle_t * devh_