point_cloud_xyz.cpp
Go to the documentation of this file.
1 
8 #include <image_transport/image_transport.h>
9 #include <pluginlib/class_list_macros.h>
10 #include <sensor_msgs/Image.h>
11 #include <cv_bridge/cv_bridge.h>
12 #include <opencv2/imgproc/imgproc.hpp>
13 #include <sensor_msgs/point_cloud2_iterator.h>
14 #include <opencv2/core/ocl.hpp>
15 #include <ros/package.h>
16 
17 // Register as nodelet
19  nodelet::Nodelet);
20 
21 namespace pses_kinect_utilities
22 {
23 
25 {
26  NODELET_DEBUG("Initializing pointcloud XYZ nodelet...");
27 
28  ros::NodeHandle& private_nh = getPrivateNodeHandle();
29  ros::NodeHandle& nh = getNodeHandle();
30 
31  current_cloud_.reset(new PointCloudMsg);
33  it_.reset(new image_transport::ImageTransport(nh));
34  kernel_ready_ = false;
35 
36  // Read parameters
37  private_nh.param("queue_size", queue_size_, 1);
38  private_nh.param<std::string>("tf_frame", tf_frame_, "kinect2_link");
39  private_nh.param<std::string>("cl_file_path", cl_file_path_,
40  ros::package::getPath("pses_kinect_utilities") +
41  "/ocl_kernel/ocl_kernel.cl");
42 
43  // Monitor whether anyone is subscribed to the output
44  ros::SubscriberStatusCallback connect_cb =
45  boost::bind(&PointCloudXYZNodelet::connectCb, this);
46  // Make sure we don't enter connectCb() between advertising and assigning to
47  boost::lock_guard<boost::mutex> lock(connect_mutex_);
48  pub_cloud_ = nh.advertise<PointCloud>("cloud_out", 1, connect_cb, connect_cb);
49 }
50 
52 {
53  boost::lock_guard<boost::mutex> lock(connect_mutex_);
54  if (pub_cloud_.getNumSubscribers() == 0)
55  {
56  NODELET_INFO("Stopping conversion from depth image to XYZ pointcloud...");
57  sub_depth_.shutdown();
58  }
59  else if (!sub_depth_)
60  {
61  NODELET_INFO("Running conversion from depth image to XYZ pointcloud...");
62  image_transport::TransportHints hints("raw", ros::TransportHints(),
63  getPrivateNodeHandle());
64  sub_depth_ = it_->subscribeCamera(
65  "depth_in", queue_size_, &PointCloudXYZNodelet::depthCb, this, hints);
66  }
67 }
68 
70  const sensor_msgs::ImageConstPtr& depth_msg,
71  const sensor_msgs::CameraInfoConstPtr& info_msg)
72 {
73  cv_bridge::CvImagePtr cv_ptr;
74 
75  try
76  {
77  cv_ptr = cv_bridge::toCvCopy(*depth_msg, depth_msg->encoding);
78  }
79  catch (cv_bridge::Exception& e)
80  {
81  NODELET_ERROR("cv_bridge exception: %s", e.what());
82  }
83 
84  // Check if opencl is available
85  if (cv::ocl::haveOpenCL())
86  {
87  // Compile and initialize the opencl kernel
88  if (!kernel_ready_)
89  {
90  kernel_ready_ = true;
91  // Initialize the camera model and compute all necessary factors.
92  camera_model_.fromCameraInfo(info_msg);
93  MetaData md;
94  md.width = (cl_uint)depth_msg->width;
95  md.height = (cl_uint)depth_msg->height;
96  md.n_pixels = (cl_uint)depth_msg->width * depth_msg->height;
97  md.depth_scaling = (cl_float)0.001f;
98  md.invalid_depth = (cl_uint)0;
99  md.max_depth = (cl_float)0.0f;
100  md.NaN = std::numeric_limits<float>::quiet_NaN();
101  Transform tf;
102  tf.cx = (cl_float)camera_model_.cx();
103  tf.cy = (cl_float)camera_model_.cy();
104  tf.fx = (cl_float)camera_model_.fx();
105  tf.fy = (cl_float)camera_model_.fy();
106  pcl_conversion_->setMetaData(md);
107  pcl_conversion_->setTFData(tf);
108  pcl_conversion_->initCloud();
109  try
110  {
111  pcl_conversion_->init_CL(cl_file_path_);
112  NODELET_INFO_STREAM(
113  "Loading opencl kernel from path: " << cl_file_path_);
114  pcl_conversion_->program_kernel("depth_to_pcl");
115  pcl_conversion_->init_buffers();
116  }
117  catch (std::exception& e)
118  {
119  NODELET_ERROR_STREAM("An error occured during OCL setup! " << e.what());
120  ros::shutdown();
121  }
122  }
123 
124  try
125  {
126  // Do the actual conversion
127  PointCloudPtr pc = pcl_conversion_->convert_to_pcl(depth_msg);
128  pc->is_dense = false;
129  pc->height = depth_msg->height;
130  pc->width = depth_msg->width;
131  pc->header.frame_id = tf_frame_;
132  pub_cloud_.publish(pc);
133  }
134  catch (std::exception& e)
135  {
136  NODELET_ERROR_STREAM("An error occured during depth to pcl conversion! "
137  << e.what());
138  }
139  }
140 
141  else // CPU variant
142  {
143  //TODO
144  NODELET_ERROR("GPU has no OpenCL support!");
145  }
146 }
147 
148 } // namespace pses_kinect_utilities
image_geometry::PinholeCameraModel camera_model_
Contains the camera calibration.
Class of the PointCloudXYZNodelet nodelet, which converts a depth image into a point cloud containing...
virtual void onInit()
This function is called by the initialization of the nodelet and acts as a constructor.
image_transport::CameraSubscriber sub_depth_
void depthCb(const sensor_msgs::ImageConstPtr &depth_msg, const sensor_msgs::CameraInfoConstPtr &info_msg)
Callback function that is called whenever a new depth image is received.
Class that make the implementation of the PointCloudXYZNodelet nodelet cleaner.
PointCloud::Ptr PointCloudPtr
Shortcut for a pointer of a XYZ Point cloud of the pcl library.
void connectCb()
Callback function that is called whenever anyone is subscribed to the output point cloud...
boost::shared_ptr< image_transport::ImageTransport > it_
sensor_msgs::PointCloud2 PointCloudMsg
Shortcut for a PointCloud2 ROS message.
Contains some parameters and metada data of the camera.
This namespace is used by the nodelets inside our package pses_kinect_utilities.
pcl::PointCloud< pcl::PointXYZ > PointCloud
Shortcut for a XYZ Point cloud of the pcl library.
PLUGINLIB_EXPORT_CLASS(pses_kinect_utilities::PointCloudXYZNodelet, nodelet::Nodelet)


pses_kinect_utilities
Author(s): Nicolas Acero
autogenerated on Sun Nov 26 2017 19:23:52