45 #include <opencv2/calib3d/calib3d.hpp>
46 #include <boost/thread.hpp>
70 boost::mutex connect_mutex_;
80 std::vector<double> D_;
81 boost::array<double, 9> K_;
89 virtual void onInit();
93 void imageCb(
const sensor_msgs::ImageConstPtr& depth_msg,
94 const sensor_msgs::ImageConstPtr& rgb_msg_in,
95 const sensor_msgs::CameraInfoConstPtr& info_msg);
99 void convert_depth(
const sensor_msgs::ImageConstPtr& depth_msg, PointCloud::Ptr& cloud_msg);
101 void convert_rgb(
const sensor_msgs::ImageConstPtr &rgb_msg, PointCloud::Ptr& cloud_msg,
102 int red_offset,
int green_offset,
int blue_offset,
int color_step);
104 cv::Mat
initMatrix(cv::Mat cameraMatrix, cv::Mat distCoeffs,
int width,
int height,
bool radial);
111 int totalsize = width*height;
112 cv::Mat pixelVectors(1,totalsize,CV_32FC3);
113 cv::Mat dst(1,totalsize,CV_32FC3);
115 cv::Mat sensorPoints(cv::Size(height,width), CV_32FC2);
116 cv::Mat undistortedSensorPoints(1,totalsize, CV_32FC2);
118 std::vector<cv::Mat> ch;
119 for(j = 0; j < height; j++)
121 for(i = 0; i < width; i++)
123 cv::Vec2f &p = sensorPoints.at<cv::Vec2f>(i,j);
129 sensorPoints = sensorPoints.reshape(2,1);
131 cv::undistortPoints(sensorPoints, undistortedSensorPoints, cameraMatrix, distCoeffs);
133 ch.push_back(undistortedSensorPoints);
134 ch.push_back(cv::Mat::ones(1,totalsize,CV_32FC1));
135 cv::merge(ch,pixelVectors);
139 for(i = 0; i < totalsize; i++)
141 normalize(pixelVectors.at<cv::Vec3f>(i),
142 dst.at<cv::Vec3f>(i));
146 return pixelVectors.reshape(3,width);
162 private_nh.
param(
"queue_size", queue_size_, 5);
164 private_nh.
param(
"exact_sync", use_exact_sync,
false);
168 exact_sync_.reset(
new ExactSynchronizer(
ExactSyncPolicy(queue_size_), sub_depth_, sub_rgb_, sub_info_) );
169 exact_sync_->registerCallback(
172 sync_.reset(
new Synchronizer(
SyncPolicy(queue_size_), sub_depth_, sub_rgb_, sub_info_) );
173 sync_->registerCallback(
180 boost::lock_guard<boost::mutex> lock(connect_mutex_);
181 pub_point_cloud_ = depth_nh.advertise<
PointCloud>(
"points", 20, connect_cb, connect_cb);
187 boost::lock_guard<boost::mutex> lock(connect_mutex_);
189 if (pub_point_cloud_.getNumSubscribers() == 0)
191 sub_depth_.unsubscribe();
192 sub_rgb_.unsubscribe();
193 sub_info_.unsubscribe();
195 else if (!sub_depth_.getSubscriber())
199 std::string depth_image_transport_param =
"depth_image_transport";
203 sub_depth_.subscribe(*depth_it_,
"image_rect", 1, depth_hints);
207 sub_rgb_.subscribe(*rgb_it_,
"image_rect_color", 1, hints);
208 sub_info_.subscribe(*rgb_nh_,
"camera_info", 1);
210 NODELET_INFO(
" subscribed to: %s", sub_rgb_.getTopic().c_str());
211 NODELET_INFO(
" subscribed to: %s", sub_depth_.getTopic().c_str());
212 NODELET_INFO(
" subscribed to: %s", sub_info_.getTopic().c_str());
217 const sensor_msgs::ImageConstPtr& rgb_msg_in,
218 const sensor_msgs::CameraInfoConstPtr& info_msg)
221 cloud_msg->header = depth_msg->header;
222 cloud_msg->height = depth_msg->height;
223 cloud_msg->width = depth_msg->width;
224 cloud_msg->is_dense =
false;
225 cloud_msg->is_bigendian =
false;
237 if (depth_msg->header.frame_id != rgb_msg_in->header.frame_id)
240 depth_msg->header.frame_id.c_str(), rgb_msg_in->header.frame_id.c_str());
245 model_.fromCameraInfo(info_msg);
248 sensor_msgs::ImageConstPtr rgb_msg = rgb_msg_in;
249 if (depth_msg->width != rgb_msg->width || depth_msg->height != rgb_msg->height)
251 sensor_msgs::CameraInfo info_msg_tmp = *info_msg;
252 info_msg_tmp.width = depth_msg->width;
253 info_msg_tmp.height = depth_msg->height;
254 float ratio = float(depth_msg->width)/float(rgb_msg->width);
255 info_msg_tmp.K[0] *= ratio;
256 info_msg_tmp.K[2] *= ratio;
257 info_msg_tmp.K[4] *= ratio;
258 info_msg_tmp.K[5] *= ratio;
259 info_msg_tmp.P[0] *= ratio;
260 info_msg_tmp.P[2] *= ratio;
261 info_msg_tmp.P[5] *= ratio;
262 info_msg_tmp.P[6] *= ratio;
263 model_.fromCameraInfo(info_msg_tmp);
273 ROS_ERROR(
"cv_bridge exception: %s", e.what());
277 cv_rsz.
header = cv_ptr->header;
279 cv::resize(cv_ptr->image.rowRange(0,depth_msg->height/ratio), cv_rsz.
image, cv::Size(depth_msg->width, depth_msg->height));
280 if ((rgb_msg->encoding == enc::RGB8) || (rgb_msg->encoding == enc::BGR8) || (rgb_msg->encoding == enc::MONO8))
293 if(info_msg->D != D_ || info_msg->K != K_ || width_ != info_msg->width ||
294 height_ != info_msg->height)
298 width_ = info_msg->width;
299 height_ = info_msg->height;
300 transform_ =
initMatrix(cv::Mat_<double>(3, 3, &K_[0]),cv::Mat(D_),width_,height_,
true);
303 if (depth_msg->encoding == enc::TYPE_16UC1)
305 convert_depth<uint16_t>(depth_msg, cloud_msg);
307 else if (depth_msg->encoding == enc::TYPE_32FC1)
309 convert_depth<float>(depth_msg, cloud_msg);
317 int red_offset, green_offset, blue_offset, color_step;
318 if(rgb_msg->encoding == enc::RGB8)
324 convert_rgb(rgb_msg, cloud_msg, red_offset, green_offset, blue_offset, color_step);
327 if(rgb_msg->encoding == enc::RGBA8)
333 convert_rgb(rgb_msg, cloud_msg, red_offset, green_offset, blue_offset, color_step);
335 else if(rgb_msg->encoding == enc::BGR8)
341 convert_rgb(rgb_msg, cloud_msg, red_offset, green_offset, blue_offset, color_step);
343 else if(rgb_msg->encoding == enc::BGRA8)
349 convert_rgb(rgb_msg, cloud_msg, red_offset, green_offset, blue_offset, color_step);
351 else if(rgb_msg->encoding == enc::MONO8)
357 convert_rgb(rgb_msg, cloud_msg, red_offset, green_offset, blue_offset, color_step);
365 pub_point_cloud_.publish (cloud_msg);
370 PointCloud::Ptr& cloud_msg)
373 double unit_scaling = DepthTraits<T>::toMeters( T(1) );
374 float bad_point = std::numeric_limits<float>::quiet_NaN();
379 const T* depth_row =
reinterpret_cast<const T*
>(&depth_msg->data[0]);
381 int row_step = depth_msg->step /
sizeof(T);
382 for (
int v = 0; v < (int)cloud_msg->height; ++v, depth_row += row_step)
384 for (
int u = 0; u < (int)cloud_msg->width; ++u, ++iter_x, ++iter_y, ++iter_z)
386 T depth = depth_row[u];
389 if (!DepthTraits<T>::valid(depth))
391 *iter_x = *iter_y = *iter_z = bad_point;
394 const cv::Vec3f &cvPoint = transform_.at<cv::Vec3f>(u,v) * DepthTraits<T>::toMeters(depth);
396 *iter_x = cvPoint(0);
397 *iter_y = cvPoint(1);
398 *iter_z = cvPoint(2);
404 PointCloud::Ptr& cloud_msg,
405 int red_offset,
int green_offset,
int blue_offset,
int color_step)
411 const uint8_t* rgb = &rgb_msg->data[0];
412 int rgb_skip = rgb_msg->step - rgb_msg->width * color_step;
414 for (
int v = 0; v < (int)cloud_msg->height; ++v, rgb += rgb_skip)
416 for (
int u = 0; u < (int)cloud_msg->width; ++u, rgb += color_step, ++iter_r, ++iter_g, ++iter_b)
418 *iter_r = rgb[red_offset];
419 *iter_g = rgb[green_offset];
420 *iter_b = rgb[blue_offset];