45 #include <Eigen/Geometry> 74 virtual void onInit();
78 void imageCb(
const sensor_msgs::ImageConstPtr& depth_image_msg,
79 const sensor_msgs::CameraInfoConstPtr& depth_info_msg,
80 const sensor_msgs::CameraInfoConstPtr& rgb_info_msg);
83 void convert(
const sensor_msgs::ImageConstPtr& depth_msg,
84 const sensor_msgs::ImagePtr& registered_msg,
85 const Eigen::Affine3d& depth_to_rgb);
100 private_nh.
param(
"queue_size", queue_size, 5);
103 sync_.reset(
new Synchronizer(
SyncPolicy(queue_size), sub_depth_image_, sub_depth_info_, sub_rgb_info_) );
111 boost::lock_guard<boost::mutex> lock(connect_mutex_);
113 image_connect_cb, image_connect_cb,
114 info_connect_cb, info_connect_cb);
120 boost::lock_guard<boost::mutex> lock(connect_mutex_);
121 if (pub_registered_.getNumSubscribers() == 0)
123 sub_depth_image_.unsubscribe();
124 sub_depth_info_ .unsubscribe();
125 sub_rgb_info_ .unsubscribe();
127 else if (!sub_depth_image_.getSubscriber())
130 sub_depth_image_.subscribe(*it_depth_,
"image_rect", 1, hints);
131 sub_depth_info_ .subscribe(*nh_depth_,
"camera_info", 1);
132 sub_rgb_info_ .subscribe(*nh_rgb_,
"camera_info", 1);
137 const sensor_msgs::CameraInfoConstPtr& depth_info_msg,
138 const sensor_msgs::CameraInfoConstPtr& rgb_info_msg)
141 depth_model_.fromCameraInfo(depth_info_msg);
142 rgb_model_ .fromCameraInfo(rgb_info_msg);
145 Eigen::Affine3d depth_to_rgb;
148 geometry_msgs::TransformStamped transform = tf_buffer_->lookupTransform (
149 rgb_info_msg->header.frame_id, depth_info_msg->header.frame_id,
150 depth_info_msg->header.stamp);
163 sensor_msgs::ImagePtr registered_msg(
new sensor_msgs::Image );
164 registered_msg->header.stamp = depth_image_msg->header.stamp;
165 registered_msg->header.frame_id = rgb_info_msg->header.frame_id;
166 registered_msg->encoding = depth_image_msg->encoding;
168 cv::Size resolution = rgb_model_.reducedResolution();
169 registered_msg->height = resolution.height;
170 registered_msg->width = resolution.width;
173 if (depth_image_msg->encoding == enc::TYPE_16UC1)
175 convert<uint16_t>(depth_image_msg, registered_msg, depth_to_rgb);
177 else if (depth_image_msg->encoding == enc::TYPE_32FC1)
179 convert<float>(depth_image_msg, registered_msg, depth_to_rgb);
183 NODELET_ERROR_THROTTLE(5,
"Depth image has unsupported encoding [%s]", depth_image_msg->encoding.c_str());
188 sensor_msgs::CameraInfoPtr registered_info_msg(
new sensor_msgs::CameraInfo(*rgb_info_msg) );
189 registered_info_msg->header.stamp = registered_msg->header.stamp;
191 pub_registered_.publish(registered_msg, registered_info_msg);
196 const sensor_msgs::ImagePtr& registered_msg,
197 const Eigen::Affine3d& depth_to_rgb)
200 registered_msg->step = registered_msg->width *
sizeof(T);
201 registered_msg->data.resize( registered_msg->height * registered_msg->step );
206 double inv_depth_fx = 1.0 / depth_model_.fx();
207 double inv_depth_fy = 1.0 / depth_model_.fy();
208 double depth_cx = depth_model_.cx(), depth_cy = depth_model_.cy();
209 double depth_Tx = depth_model_.Tx(), depth_Ty = depth_model_.Ty();
210 double rgb_fx = rgb_model_.fx(), rgb_fy = rgb_model_.fy();
211 double rgb_cx = rgb_model_.cx(), rgb_cy = rgb_model_.cy();
212 double rgb_Tx = rgb_model_.Tx(), rgb_Ty = rgb_model_.Ty();
216 const T* depth_row =
reinterpret_cast<const T*
>(&depth_msg->data[0]);
217 int row_step = depth_msg->step /
sizeof(T);
218 T* registered_data =
reinterpret_cast<T*
>(®istered_msg->data[0]);
220 for (
unsigned v = 0; v < depth_msg->height; ++v, depth_row += row_step)
222 for (
unsigned u = 0; u < depth_msg->width; ++u, ++raw_index)
224 T raw_depth = depth_row[u];
232 Eigen::Vector4d xyz_depth;
233 xyz_depth << ((u - depth_cx)*depth - depth_Tx) * inv_depth_fx,
234 ((v - depth_cy)*depth - depth_Ty) * inv_depth_fy,
239 Eigen::Vector4d xyz_rgb = depth_to_rgb * xyz_depth;
242 double inv_Z = 1.0 / xyz_rgb.z();
243 int u_rgb = (rgb_fx*xyz_rgb.x() + rgb_Tx)*inv_Z + rgb_cx + 0.5;
244 int v_rgb = (rgb_fy*xyz_rgb.y() + rgb_Ty)*inv_Z + rgb_cy + 0.5;
246 if (u_rgb < 0 || u_rgb >= (
int)registered_msg->width ||
247 v_rgb < 0 || v_rgb >= (int)registered_msg->height)
250 T& reg_depth = registered_data[v_rgb*registered_msg->width + u_rgb];
254 reg_depth = new_depth;
void convert(const sensor_msgs::ImageConstPtr &depth_msg, PointCloud::Ptr &cloud_msg, const image_geometry::PinholeCameraModel &model, double range_max=0.0)
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
boost::shared_ptr< Synchronizer > sync_
message_filters::Subscriber< sensor_msgs::CameraInfo > sub_rgb_info_
ros::NodeHandlePtr nh_rgb_
#define NODELET_ERROR_THROTTLE(rate,...)
ExactTime< sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo > SyncPolicy
boost::shared_ptr< image_transport::ImageTransport > it_depth_
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
boost::shared_ptr< tf2_ros::TransformListener > tf_
image_geometry::PinholeCameraModel rgb_model_
CameraPublisher advertiseCamera(const std::string &base_topic, uint32_t queue_size, bool latch=false)
#define NODELET_WARN_THROTTLE(rate,...)
image_transport::SubscriberFilter sub_depth_image_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void imageCb(const sensor_msgs::ImageConstPtr &depth_image_msg, const sensor_msgs::CameraInfoConstPtr &depth_info_msg, const sensor_msgs::CameraInfoConstPtr &rgb_info_msg)
void transformMsgToEigen(const geometry_msgs::Transform &m, Eigen::Affine3d &e)
PLUGINLIB_EXPORT_CLASS(depth_image_proc::RegisterNodelet, nodelet::Nodelet)
void convert(const sensor_msgs::ImageConstPtr &depth_msg, const sensor_msgs::ImagePtr ®istered_msg, const Eigen::Affine3d &depth_to_rgb)
boost::mutex connect_mutex_
image_transport::CameraPublisher pub_registered_
boost::shared_ptr< tf2_ros::Buffer > tf_buffer_
ApproximateTime< sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo > SyncPolicy
message_filters::Synchronizer< SyncPolicy > Synchronizer