34 #include <boost/version.hpp>
35 #if ((BOOST_VERSION / 100) % 1000) >= 53
36 #include <boost/thread/lock_guard.hpp>
48 #include <sensor_msgs/PointCloud2.h>
52 #include <opencv2/imgproc/imgproc.hpp>
72 boost::mutex connect_mutex_;
78 virtual void onInit();
82 void imageCb(
const sensor_msgs::ImageConstPtr& depth_msg,
83 const sensor_msgs::ImageConstPtr& intensity_msg,
84 const sensor_msgs::CameraInfoConstPtr& info_msg);
86 template<
typename T,
typename T2>
87 void convert(
const sensor_msgs::ImageConstPtr& depth_msg,
88 const sensor_msgs::ImageConstPtr& intensity_msg,
89 const PointCloud::Ptr& cloud_msg);
103 private_nh.
param(
"queue_size", queue_size, 5);
107 sync_->registerCallback(boost::bind(&
PointCloudXyziNodelet::imageCb,
this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3));
112 boost::lock_guard<boost::mutex> lock(connect_mutex_);
113 pub_point_cloud_ = depth_nh.advertise<
PointCloud>(
"points", 1, connect_cb, connect_cb);
119 boost::lock_guard<boost::mutex> lock(connect_mutex_);
120 if (pub_point_cloud_.getNumSubscribers() == 0)
122 sub_depth_.unsubscribe();
123 sub_intensity_ .unsubscribe();
124 sub_info_ .unsubscribe();
126 else if (!sub_depth_.getSubscriber())
130 std::string depth_image_transport_param =
"depth_image_transport";
134 sub_depth_.subscribe(*depth_it_,
"image_rect", 1, depth_hints);
138 sub_intensity_.subscribe(*intensity_it_,
"image_rect", 1, hints);
139 sub_info_.subscribe(*intensity_nh_,
"camera_info", 1);
144 const sensor_msgs::ImageConstPtr& intensity_msg_in,
145 const sensor_msgs::CameraInfoConstPtr& info_msg)
148 if (depth_msg->header.frame_id != intensity_msg_in->header.frame_id)
151 depth_msg->header.frame_id.c_str(), intensity_msg_in->header.frame_id.c_str());
156 model_.fromCameraInfo(info_msg);
159 sensor_msgs::ImageConstPtr intensity_msg = intensity_msg_in;
160 if (depth_msg->width != intensity_msg->width || depth_msg->height != intensity_msg->height)
162 sensor_msgs::CameraInfo info_msg_tmp = *info_msg;
163 info_msg_tmp.width = depth_msg->width;
164 info_msg_tmp.height = depth_msg->height;
165 float ratio = float(depth_msg->width)/float(intensity_msg->width);
166 info_msg_tmp.K[0] *= ratio;
167 info_msg_tmp.K[2] *= ratio;
168 info_msg_tmp.K[4] *= ratio;
169 info_msg_tmp.K[5] *= ratio;
170 info_msg_tmp.P[0] *= ratio;
171 info_msg_tmp.P[2] *= ratio;
172 info_msg_tmp.P[5] *= ratio;
173 info_msg_tmp.P[6] *= ratio;
174 model_.fromCameraInfo(info_msg_tmp);
183 ROS_ERROR(
"cv_bridge exception: %s", e.what());
187 cv_rsz.
header = cv_ptr->header;
189 cv::resize(cv_ptr->image.rowRange(0,depth_msg->height/ratio), cv_rsz.
image, cv::Size(depth_msg->width, depth_msg->height));
190 if ((intensity_msg->encoding == enc::MONO8) || (intensity_msg->encoding == enc::MONO16))
199 intensity_msg = intensity_msg_in;
202 if (intensity_msg->encoding != enc::MONO8 && intensity_msg->encoding != enc::MONO16)
217 cloud_msg->header = depth_msg->header;
218 cloud_msg->height = depth_msg->height;
219 cloud_msg->width = depth_msg->width;
220 cloud_msg->is_dense =
false;
221 cloud_msg->is_bigendian =
false;
225 pcd_modifier.setPointCloud2Fields(4,
226 "x", 1, sensor_msgs::PointField::FLOAT32,
227 "y", 1, sensor_msgs::PointField::FLOAT32,
228 "z", 1, sensor_msgs::PointField::FLOAT32,
229 "intensity", 1, sensor_msgs::PointField::FLOAT32);
232 if (depth_msg->encoding == enc::TYPE_16UC1 &&
233 intensity_msg->encoding == enc::MONO8)
235 convert<uint16_t, uint8_t>(depth_msg, intensity_msg, cloud_msg);
237 else if (depth_msg->encoding == enc::TYPE_16UC1 &&
238 intensity_msg->encoding == enc::MONO16)
240 convert<uint16_t, uint16_t>(depth_msg, intensity_msg, cloud_msg);
242 else if (depth_msg->encoding == enc::TYPE_16UC1 &&
243 intensity_msg->encoding == enc::TYPE_32FC1)
245 convert<uint16_t,float>(depth_msg, intensity_msg, cloud_msg);
247 else if (depth_msg->encoding == enc::TYPE_32FC1 &&
248 intensity_msg->encoding == enc::MONO8)
250 convert<float, uint8_t>(depth_msg, intensity_msg, cloud_msg);
252 else if (depth_msg->encoding == enc::TYPE_32FC1 &&
253 intensity_msg->encoding == enc::MONO16)
255 convert<float, uint16_t>(depth_msg, intensity_msg, cloud_msg);
257 else if (depth_msg->encoding == enc::TYPE_32FC1 &&
258 intensity_msg->encoding == enc::TYPE_32FC1)
260 convert<float,float>(depth_msg, intensity_msg, cloud_msg);
268 pub_point_cloud_.publish (cloud_msg);
271 template<
typename T,
typename T2>
273 const sensor_msgs::ImageConstPtr& intensity_msg,
274 const PointCloud::Ptr& cloud_msg)
277 float center_x = model_.cx();
278 float center_y = model_.cy();
281 double unit_scaling = DepthTraits<T>::toMeters( T(1) );
282 float constant_x = unit_scaling / model_.fx();
283 float constant_y = unit_scaling / model_.fy();
284 float bad_point = std::numeric_limits<float>::quiet_NaN ();
286 const T* depth_row =
reinterpret_cast<const T*
>(&depth_msg->data[0]);
287 int row_step = depth_msg->step /
sizeof(T);
289 const T2* inten_row =
reinterpret_cast<const T2*
>(&intensity_msg->data[0]);
290 int inten_row_step = intensity_msg->step /
sizeof(T2);
297 for (
int v = 0; v < int(cloud_msg->height); ++v, depth_row += row_step, inten_row += inten_row_step)
299 for (
int u = 0; u < int(cloud_msg->width); ++u, ++iter_x, ++iter_y, ++iter_z, ++iter_i)
301 T depth = depth_row[u];
302 T2 inten = inten_row[u];
306 *iter_x = *iter_y = *iter_z = bad_point;
311 *iter_x = (u - center_x) * depth * constant_x;
312 *iter_y = (v - center_y) * depth * constant_y;