00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #define BOOST_PARAMETER_MAX_ARITY 7
00036
00037 #include <sstream>
00038 #include "jsk_pcl_ros/incremental_model_registration.h"
00039 #include "jsk_recognition_utils/pcl_conversion_util.h"
00040 #include <pcl/common/transforms.h>
00041 #include <pcl/filters/extract_indices.h>
00042 #include <jsk_recognition_msgs/ICPAlign.h>
00043
00044 namespace jsk_pcl_ros
00045 {
00046 CapturedSamplePointCloud::CapturedSamplePointCloud()
00047 {
00048
00049 }
00050
00051 CapturedSamplePointCloud::CapturedSamplePointCloud(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud,
00052 const Eigen::Affine3f& pose):
00053 original_cloud_(cloud), original_pose_(pose),
00054 refined_cloud_(new pcl::PointCloud<pcl::PointXYZRGB>)
00055 {
00056
00057 }
00058
00059 pcl::PointCloud<pcl::PointXYZRGB>::Ptr
00060 CapturedSamplePointCloud::getOriginalPointCloud()
00061 {
00062 return original_cloud_;
00063 }
00064
00065 Eigen::Affine3f CapturedSamplePointCloud::getOriginalPose()
00066 {
00067 return original_pose_;
00068 }
00069
00070 pcl::PointCloud<pcl::PointXYZRGB>::Ptr
00071 CapturedSamplePointCloud::getRefinedPointCloud()
00072 {
00073 return refined_cloud_;
00074 }
00075
00076 Eigen::Affine3f CapturedSamplePointCloud::getRefinedPose()
00077 {
00078 return refined_pose_;
00079 }
00080
00081 void CapturedSamplePointCloud::setRefinedPointCloud(
00082 pcl::PointCloud<pcl::PointXYZRGB> cloud)
00083 {
00084 *refined_cloud_ = cloud;
00085 }
00086
00087 void CapturedSamplePointCloud::setRefinedPose(
00088 Eigen::Affine3f pose)
00089 {
00090 refined_pose_ = Eigen::Affine3f(pose);
00091 }
00092
00093 void IncrementalModelRegistration::onInit()
00094 {
00095 DiagnosticNodelet::onInit();
00096 pnh_->param("frame_id", frame_id_,
00097 std::string("multisense/left_camera_optical_frame"));
00098 start_registration_srv_
00099 = pnh_->advertiseService(
00100 "start_registration", &IncrementalModelRegistration::startRegistration,
00101 this);
00102 pub_cloud_non_registered_
00103 = pnh_->advertise<sensor_msgs::PointCloud2>("output/non_registered", 1);
00104 pub_registered_
00105 = pnh_->advertise<sensor_msgs::PointCloud2>("output/registered", 1);
00106 sub_cloud_.subscribe(*pnh_, "input", 1);
00107 sub_indices_.subscribe(*pnh_, "input/indices", 1);
00108 sub_pose_.subscribe(*pnh_, "input/pose", 1);
00109 sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
00110 sync_->connectInput(sub_cloud_, sub_indices_, sub_pose_);
00111 sync_->registerCallback(boost::bind(
00112 &IncrementalModelRegistration::newsampleCallback,
00113 this, _1, _2, _3));
00114 onInitPostProcess();
00115 }
00116
00117 void IncrementalModelRegistration::transformPointCloudRepsectedToPose(
00118 pcl::PointCloud<pcl::PointXYZRGB>::Ptr input,
00119 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output,
00120 const geometry_msgs::PoseStamped::ConstPtr& pose_msg)
00121 {
00122 Eigen::Affine3f posef;
00123 tf::poseMsgToEigen(pose_msg->pose, posef);
00124 Eigen::Affine3f transform = posef.inverse();
00125
00126 pcl::transformPointCloud<pcl::PointXYZRGB>(
00127 *input, *output, transform);
00128 }
00129
00130 void IncrementalModelRegistration::newsampleCallback(
00131 const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
00132 const pcl_msgs::PointIndices::ConstPtr& indices_msg,
00133 const geometry_msgs::PoseStamped::ConstPtr& pose_msg)
00134 {
00135 boost::mutex::scoped_lock lock(mutex_);
00136 pcl::PointCloud<pcl::PointXYZRGB>::Ptr
00137 cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
00138 pcl::PointCloud<pcl::PointXYZRGB>::Ptr
00139 filtered_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
00140 pcl::fromROSMsg(*cloud_msg, *cloud);
00141 pcl::PointCloud<pcl::PointXYZRGB>::Ptr
00142 transformed_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
00143 pcl::PointIndices::Ptr
00144 indices (new pcl::PointIndices);
00145 indices->indices = indices_msg->indices;
00146 pcl::ExtractIndices<pcl::PointXYZRGB> ex;
00147 ex.setInputCloud(cloud);
00148 ex.setIndices(indices);
00149 ex.filter(*filtered_cloud);
00150 transformPointCloudRepsectedToPose(
00151 filtered_cloud, transformed_cloud, pose_msg);
00152 Eigen::Affine3f initial_pose;
00153 if (samples_.size() == 0) {
00154
00155 tf::poseMsgToEigen(pose_msg->pose, origin_);
00156 initial_pose = origin_;
00157 }
00158 else {
00159
00160 Eigen::Affine3f offset;
00161 tf::poseMsgToEigen(pose_msg->pose, offset);
00162 initial_pose = origin_.inverse() * offset;
00163 }
00164 CapturedSamplePointCloud::Ptr sample (new CapturedSamplePointCloud(transformed_cloud, initial_pose));
00165 samples_.push_back(sample);
00166
00167 all_cloud_ = all_cloud_ + *transformed_cloud;
00168 sensor_msgs::PointCloud2 ros_all_cloud;
00169 pcl::toROSMsg(all_cloud_, ros_all_cloud);
00170 ros_all_cloud.header = cloud_msg->header;
00171 pub_cloud_non_registered_.publish(ros_all_cloud);
00172 }
00173
00174 void IncrementalModelRegistration::callICP(
00175 pcl::PointCloud<pcl::PointXYZRGB>::Ptr reference,
00176 pcl::PointCloud<pcl::PointXYZRGB>::Ptr target,
00177 Eigen::Affine3f& output_transform)
00178 {
00179 ros::ServiceClient icp
00180 = pnh_->serviceClient<jsk_recognition_msgs::ICPAlign>("icp_service");
00181 sensor_msgs::PointCloud2 reference_ros, target_ros;
00182 pcl::toROSMsg(*reference, reference_ros);
00183 pcl::toROSMsg(*target, target_ros);
00184 ros::Time now = ros::Time::now();
00185 reference_ros.header.stamp = target_ros.header.stamp = now;
00186 reference_ros.header.frame_id = target_ros.header.frame_id = "map";
00187 jsk_recognition_msgs::ICPAlign srv;
00188 srv.request.reference_cloud = reference_ros;
00189 srv.request.target_cloud = target_ros;
00190 icp.call(srv);
00191 tf::poseMsgToEigen(srv.response.result.pose,
00192 output_transform);
00193 }
00194
00195 bool IncrementalModelRegistration::startRegistration(
00196 std_srvs::Empty::Request& req,
00197 std_srvs::Empty::Response& res)
00198 {
00199 if (samples_.size() <= 1) {
00200 ROS_ERROR("no enough samples");
00201 return false;
00202 }
00203 ROS_INFO("Starting registration %lu samples", samples_.size());
00204
00205 CapturedSamplePointCloud::Ptr initial_sample = samples_[0];
00206 initial_sample->setRefinedPointCloud(
00207 *(initial_sample->getOriginalPointCloud()));
00208 initial_sample->setRefinedPose(initial_sample->getOriginalPose());
00209 for (size_t i = 0; i < samples_.size() - 1; i++) {
00210 CapturedSamplePointCloud::Ptr from_sample = samples_[i];
00211 CapturedSamplePointCloud::Ptr to_sample = samples_[i+1];
00212 pcl::PointCloud<pcl::PointXYZRGB>::Ptr reference_cloud
00213 = from_sample->getRefinedPointCloud();
00214 pcl::PointCloud<pcl::PointXYZRGB>::Ptr target_cloud
00215 = to_sample->getOriginalPointCloud();
00216 Eigen::Affine3f transform;
00217 callICP(reference_cloud, target_cloud, transform);
00218 to_sample->setRefinedPose(to_sample->getOriginalPose() * transform);
00219
00220 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed_cloud
00221 (new pcl::PointCloud<pcl::PointXYZRGB>);
00222 pcl::transformPointCloud<pcl::PointXYZRGB>(
00223 *target_cloud, *transformed_cloud, transform);
00224 to_sample->setRefinedPointCloud(*transformed_cloud);
00225 }
00226 pcl::PointCloud<pcl::PointXYZRGB>::Ptr registered_cloud
00227 (new pcl::PointCloud<pcl::PointXYZRGB>);
00228 pcl::PointCloud<pcl::PointXYZRGB>::Ptr non_registered_cloud
00229 (new pcl::PointCloud<pcl::PointXYZRGB>);
00230 for (size_t i = 0; i < samples_.size(); i++) {
00231 *registered_cloud = *(samples_[i]->getRefinedPointCloud()) + *registered_cloud;
00232 *non_registered_cloud = *(samples_[i]->getOriginalPointCloud()) + *non_registered_cloud;
00233 }
00234 sensor_msgs::PointCloud2 registered_ros_cloud, nonregistered_ros_cloud;
00235 pcl::toROSMsg(*registered_cloud, registered_ros_cloud);
00236 registered_ros_cloud.header.stamp = ros::Time::now();
00237 registered_ros_cloud.header.frame_id = frame_id_;
00238 pub_registered_.publish(registered_ros_cloud);
00239 pcl::toROSMsg(*non_registered_cloud, nonregistered_ros_cloud);
00240 nonregistered_ros_cloud.header.stamp = ros::Time::now();
00241 nonregistered_ros_cloud.header.frame_id = frame_id_;
00242 pub_cloud_non_registered_.publish(nonregistered_ros_cloud);
00243 }
00244
00245 }
00246
00247 #include <pluginlib/class_list_macros.h>
00248 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::IncrementalModelRegistration, nodelet::Nodelet);