kinfu_nodelet.cpp
Go to the documentation of this file.
00001 // -*- mode: c++ -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2014, JSK Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/o2r other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the JSK Lab nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 #include "jsk_pcl_ros/kinfu.h"
00037 #include <geometry_msgs/PoseStamped.h>
00038 #include "jsk_pcl_ros/pcl_conversion_util.h"
00039 #include <pcl/common/transforms.h>
00040 #include <cv_bridge/cv_bridge.h>
00041 
00042 namespace jsk_pcl_ros
00043 {
00044   void Kinfu::subscribe()
00045   {
00046 
00047   }
00048 
00049   void Kinfu::unsubscribe()
00050   {
00051 
00052   }
00053 
00054   void Kinfu::onInit()
00055   {
00056     DiagnosticNodelet::onInit();
00057     initialized_ = false;
00058     tf_listener_ = TfListenerSingleton::getInstance();
00059     pnh_->param("parent_frame_id", parent_frame_id_, std::string("map"));
00060     pnh_->param("child_frame_id", child_frame_id_, std::string("odom"));
00061     pnh_->param("kinfu_origin_frame_id", kinfu_origin_frame_id_, std::string("kinfu_origin"));
00062     pcl::gpu::setDevice(0);
00063     pcl::gpu::printShortCudaDeviceInfo(0);
00064     volume_size_ = pcl::device::kinfuLS::VOLUME_SIZE;
00065     shift_distance_ = pcl::device::kinfuLS::DISTANCE_THRESHOLD;
00066     snapshot_rate_ = pcl::device::kinfuLS::SNAPSHOT_RATE;
00067     pub_pose_ = pnh_->advertise<geometry_msgs::PoseStamped>("output", 1);
00068     pub_cloud_ = pnh_->advertise<sensor_msgs::PointCloud2>("output/cloud", 1);
00069     sub_depth_image_.subscribe(*pnh_, "input/depth", 1);
00070     sub_color_image_.subscribe(*pnh_, "input/color", 1);
00071     sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
00072     sync_->connectInput(sub_depth_image_, sub_color_image_);
00073     sync_->registerCallback(boost::bind(&Kinfu::callback, this, _1, _2));
00074     sub_info_ = pnh_->subscribe("input/info", 1, &Kinfu::infoCallback, this);
00075   }
00076 
00077   void Kinfu::infoCallback(const sensor_msgs::CameraInfo::ConstPtr& info_msg)
00078   {
00079     boost::mutex::scoped_lock lock(mutex_);
00080     info_msg_ = info_msg;
00081   }
00082 
00083   void Kinfu::callback(const sensor_msgs::Image::ConstPtr& depth_image,
00084                        const sensor_msgs::Image::ConstPtr& rgb_image)
00085   {
00086     boost::mutex::scoped_lock lock(mutex_);
00087     if (!info_msg_) {
00088       JSK_NODELET_WARN("camera info is not yet ready");
00089       return;
00090     }
00091     if (!initialized_) {
00092       Eigen::Vector3f volume_size = Eigen::Vector3f::Constant (volume_size_);
00093       
00094       // Setup kinfu
00095       kinfu_ = new pcl::gpu::kinfuLS::KinfuTracker(volume_size, 
00096                                                    shift_distance_,
00097                                                    info_msg_->height,
00098                                                    info_msg_->width);
00099       kinfu_->setInitialCameraPose(Eigen::Affine3f::Identity());
00100       kinfu_->volume().setTsdfTruncDist (0.030f/*meters*/);
00101       kinfu_->setIcpCorespFilteringParams (0.1f/*meters*/, sin ( pcl::deg2rad(20.f) ));
00102       kinfu_->setCameraMovementThreshold(0.001f);
00103       kinfu_->setDepthIntrinsics (info_msg_->K[0], info_msg_->K[4], info_msg_->K[2], info_msg_->K[5]);
00104       initialized_ = true;
00105       initial_camera_pose_acquired_ = false;
00106     }
00107     if (kinfu_->icpIsLost()) {
00108       kinfu_->reset();
00109       JSK_NODELET_FATAL("kinfu is reset");
00110     }
00111     
00112     if (!initial_camera_pose_acquired_) {
00113       // First we need to check odometry is available or not
00114       try {
00115         // odom -> camera
00116         tf::StampedTransform trans = 
00117           lookupTransformWithDuration(tf_listener_,
00118                                       info_msg_->header.frame_id,
00119                                       child_frame_id_,
00120                                       depth_image->header.stamp,
00121                                       ros::Duration(1.0));
00122         tf::transformTFToEigen(trans, initial_camera_pose_);
00123       }
00124       catch (...) {
00125         JSK_NODELET_ERROR("Failed to lookup transform from %s to %s",
00126                           child_frame_id_.c_str(),
00127                           info_msg_->header.frame_id.c_str());
00128         return;
00129       }
00130     }
00131 
00132     cv::Mat depth_m_image = cv_bridge::toCvShare(depth_image, "32FC1")->image;
00133     cv::Mat depth_mm_image = depth_m_image * 1000.0;
00134     cv::Mat depth_mm_sc_image;
00135     depth_mm_image.convertTo(depth_mm_sc_image, CV_16UC1);
00136     depth_device_.upload(&(depth_mm_sc_image.data[0]), depth_image->width * 2, depth_image->height, depth_image->width);
00137     //colors_device_.upload(&(rgb_image->data[0]), rgb_image->step, rgb_image->height, rgb_image->width);
00138 
00139     //(*kinfu_)(depth_device_, colors_device_);
00140     (*kinfu_)(depth_device_);
00141     Eigen::Affine3f camera_pose = kinfu_->getCameraPose();
00142     if (!initial_camera_pose_acquired_) {
00143       initial_kinfu_pose_ = camera_pose;
00144       initial_camera_pose_acquired_ = true;
00145     }
00146     else {
00147       Eigen::Affine3f K = initial_kinfu_pose_.inverse() * camera_pose;
00148       // TODO: we should use tf message filter
00149       try {
00150         // odom -> camera
00151         tf::StampedTransform trans = 
00152           lookupTransformWithDuration(tf_listener_,
00153                                       depth_image->header.frame_id,
00154                                       child_frame_id_,
00155                                       depth_image->header.stamp,
00156                                       ros::Duration(0.1));
00157         Eigen::Affine3f odom_camera;
00158         tf::transformTFToEigen(trans, odom_camera);
00159         Eigen::Affine3f map = initial_camera_pose_ * K * odom_camera.inverse();
00160         tf::Transform map_odom_transform;
00161         tf::transformEigenToTF(map, map_odom_transform);
00162         tf_broadcaster_.sendTransform(tf::StampedTransform(
00163                                                            map_odom_transform,
00164                                                            depth_image->header.stamp,
00165                                                            parent_frame_id_,
00166                                                            child_frame_id_));
00167         tf::Transform kinfu_origin;
00168         Eigen::Affine3f inverse_camera_pose = camera_pose.inverse();
00169         tf::transformEigenToTF(inverse_camera_pose, kinfu_origin);
00170         tf_broadcaster_.sendTransform(tf::StampedTransform(
00171                                                            kinfu_origin,
00172                                                            depth_image->header.stamp,
00173                                                            depth_image->header.frame_id,
00174                                                            kinfu_origin_frame_id_));
00175         Eigen::Affine3f camera_diff = K.inverse();
00176         geometry_msgs::PoseStamped ros_camera_diff;
00177         tf::poseEigenToMsg(camera_diff, ros_camera_diff.pose);
00178         ros_camera_diff.header = depth_image->header;
00179         pub_pose_.publish(ros_camera_diff);
00180 
00181         // scene cloud.
00182         pcl::gpu::DeviceArray<pcl::PointXYZ> extracted = kinfu_->volume().fetchCloud(cloud_buffer_device_);             
00183         pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
00184         pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud(new pcl::PointCloud<pcl::PointXYZ>);
00185         extracted.download (cloud->points);
00186         cloud->width = (int)cloud->points.size ();
00187         cloud->height = 1;
00188         //pcl::transformPointCloud(*cloud, *transformed_cloud, camera_pose.inverse());
00189         sensor_msgs::PointCloud2 ros_cloud;
00190         pcl::toROSMsg(*cloud, ros_cloud);
00191         ros_cloud.header.stamp = depth_image->header.stamp;
00192         ros_cloud.header.frame_id = kinfu_origin_frame_id_;
00193         pub_cloud_.publish(ros_cloud);
00194       }
00195       catch (...) {
00196         JSK_NODELET_ERROR("Failed to lookup transform from %s to %s",
00197                           child_frame_id_.c_str(),
00198                           depth_image->header.frame_id.c_str());
00199         return;
00200       }
00201     }
00202   }
00203                        
00204 }
00205 
00206 #include <pluginlib/class_list_macros.h>
00207 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::Kinfu,
00208                         nodelet::Nodelet);


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Wed Sep 16 2015 04:36:47