36 #define BOOST_PARAMETER_MAX_ARITY 7
39 #include <pcl/features/normal_3d.h>
40 #include <pcl/kdtree/kdtree_flann.h>
41 #include <pcl/common/transforms.h>
42 #include <pcl/filters/passthrough.h>
50 inline float NORM(
float vx,
float vy,
float vz){
return sqrt(vx*vx+vy*vy+vz*vz);}
54 void HintedHandleEstimator::onInit()
56 DiagnosticNodelet::onInit();
57 pub_pose_ = advertise<geometry_msgs::PoseStamped>(
58 *pnh_,
"handle_pose", 1);
59 pub_length_ = advertise<std_msgs::Float64>(
60 *pnh_,
"handle_length", 1);
61 pub_handle_ = advertise<jsk_recognition_msgs::SimpleHandle>(
63 pub_debug_marker_ = advertise<visualization_msgs::Marker>(*pnh_,
"debug_marker", 1);
64 pub_debug_marker_array_ = advertise<visualization_msgs::MarkerArray>(*pnh_,
"debug_marker_array", 1);
66 pnh_->param(
"finger_l", handle.finger_l, 0.03);
67 pnh_->param(
"finger_d", handle.finger_d, 0.02);
68 pnh_->param(
"finger_w", handle.finger_w, 0.01);
69 pnh_->param(
"arm_l", handle.arm_l, 0.05);
70 pnh_->param(
"arm_d", handle.arm_d, 0.02);
71 pnh_->param(
"arm_w", handle.arm_w, 0.1);
75 HintedHandleEstimator::~HintedHandleEstimator() {
86 void HintedHandleEstimator::subscribe()
88 sub_cloud_.subscribe(*pnh_,
"cloud", 1);
89 sub_point_.subscribe(*pnh_,
"point", 1);
90 sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
91 sync_->connectInput(sub_cloud_, sub_point_);
92 sync_->registerCallback(boost::bind(&HintedHandleEstimator::estimate,
this,
_1,
_2));
95 void HintedHandleEstimator::unsubscribe()
97 sub_cloud_.unsubscribe();
98 sub_point_.unsubscribe();
101 void HintedHandleEstimator::estimate(
102 const sensor_msgs::PointCloud2::ConstPtr& cloud_msg,
103 const geometry_msgs::PointStampedConstPtr &point_msg)
106 pcl::PointCloud<pcl::PointXYZ>::Ptr
cloud(
new pcl::PointCloud<pcl::PointXYZ>);
107 pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(
new pcl::PointCloud<pcl::Normal>);
108 pcl::PassThrough<pcl::PointXYZ> pass;
110 std::vector<int> pointIdxNKNSearch(
K);
111 std::vector<float> pointNKNSquaredDistance(
K);
112 pcl::search::KdTree<pcl::PointXYZ>::Ptr kd_tree(
new pcl::search::KdTree<pcl::PointXYZ>);
115 geometry_msgs::PointStamped transed_point;
119 listener_.waitForTransform(
cloud->header.frame_id, point_msg->header.frame_id,
now,
ros::Duration(1.0));
120 listener_.transformPoint(
cloud->header.frame_id,
now, *point_msg, point_msg->header.frame_id, transed_point);
127 pcl::PointXYZ searchPoint;
128 searchPoint.x = transed_point.point.x;
129 searchPoint.y = transed_point.point.y;
130 searchPoint.z = transed_point.point.z;
133 pass.setInputCloud(
cloud);
134 pass.setFilterFieldName(
"x");
135 pass.setFilterLimits(searchPoint.x - 3*handle.arm_w, searchPoint.x + 3*handle.arm_w);
137 pass.setInputCloud(
cloud);
138 pass.setFilterFieldName(
"y");
139 pass.setFilterLimits(searchPoint.y - 3*handle.arm_w, searchPoint.y + 3*handle.arm_w);
141 pass.setInputCloud(
cloud);
142 pass.setFilterFieldName(
"z");
143 pass.setFilterLimits(searchPoint.z - 3*handle.arm_w, searchPoint.z + 3*handle.arm_w);
146 if(
cloud->points.size() < 10){
151 pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
152 ne.setInputCloud(
cloud);
153 ne.setSearchMethod(kd_tree);
154 ne.setRadiusSearch(0.02);
155 ne.setViewPoint(0, 0, 0);
156 ne.compute(*cloud_normals);
161 if(! (kd_tree->nearestKSearch (searchPoint,
K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)){
165 float x =
cloud->points[pointIdxNKNSearch[0]].x;
166 float y =
cloud->points[pointIdxNKNSearch[0]].y;
167 float z =
cloud->points[pointIdxNKNSearch[0]].z;
168 float v_x = cloud_normals->points[pointIdxNKNSearch[0]].normal_x;
169 float v_y = cloud_normals->points[pointIdxNKNSearch[0]].normal_y;
170 float v_z = cloud_normals->points[pointIdxNKNSearch[0]].normal_z;
171 double theta = acos(v_x);
175 double min_theta_index = 0;
176 double min_width = 100;
178 visualization_msgs::Marker debug_hand_marker;
179 debug_hand_marker.header = cloud_msg->header;
180 debug_hand_marker.ns =
string(
"debug_grasp");
181 debug_hand_marker.id = 0;
182 debug_hand_marker.type = visualization_msgs::Marker::LINE_LIST;
183 debug_hand_marker.pose.orientation.w = 1;
184 debug_hand_marker.scale.x=0.003;
187 for(
double theta_=0; theta_<3.14/2;
192 geometry_msgs::Pose pose_respected_to_tf;
193 pose_respected_to_tf.position.x =
x;
194 pose_respected_to_tf.position.y =
y;
195 pose_respected_to_tf.position.z =
z;
196 pose_respected_to_tf.orientation.x = temp_qua.getX();
197 pose_respected_to_tf.orientation.y = temp_qua.getY();
198 pose_respected_to_tf.orientation.z = temp_qua.getZ();
199 pose_respected_to_tf.orientation.w = temp_qua.
getW();
200 Eigen::Affine3d box_pose_respected_to_cloud_eigend;
202 Eigen::Affine3d box_pose_respected_to_cloud_eigend_inversed
203 = box_pose_respected_to_cloud_eigend.inverse();
204 Eigen::Matrix4f box_pose_respected_to_cloud_eigen_inversed_matrixf;
205 Eigen::Matrix4d box_pose_respected_to_cloud_eigen_inversed_matrixd
206 = box_pose_respected_to_cloud_eigend_inversed.matrix();
207 jsk_recognition_utils::convertMatrix4<Eigen::Matrix4d, Eigen::Matrix4f>(
208 box_pose_respected_to_cloud_eigen_inversed_matrixd,
209 box_pose_respected_to_cloud_eigen_inversed_matrixf);
210 Eigen::Affine3f offset = Eigen::Affine3f(box_pose_respected_to_cloud_eigen_inversed_matrixf);
211 pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
212 pcl::transformPointCloud(*
cloud, *output_cloud, offset);
214 pcl::PassThrough<pcl::PointXYZ> pass;
215 pcl::PointCloud<pcl::PointXYZ>::Ptr points_z(
new pcl::PointCloud<pcl::PointXYZ>), points_yz(
new pcl::PointCloud<pcl::PointXYZ>), points_xyz(
new pcl::PointCloud<pcl::PointXYZ>);
216 pass.setInputCloud(output_cloud);
217 pass.setFilterFieldName(
"y");
218 pass.setFilterLimits(-handle.arm_w*2, handle.arm_w*2);
219 pass.filter(*points_z);
220 pass.setInputCloud(points_z);
221 pass.setFilterFieldName(
"z");
222 pass.setFilterLimits(-handle.finger_d, handle.finger_d);
223 pass.filter(*points_yz);
224 pass.setInputCloud(points_yz);
225 pass.setFilterFieldName(
"x");
226 pass.setFilterLimits(-(handle.arm_l-handle.finger_l), handle.finger_l);
227 pass.filter(*points_xyz);
228 pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
230 points_xyz->points[
index].x = points_xyz->points[
index].z = 0;
232 if(points_xyz->points.size() == 0){
ROS_INFO(
"points are empty");
return;}
233 kdtree.setInputCloud(points_xyz);
234 std::vector<int> pointIdxRadiusSearch;
235 std::vector<float> pointRadiusSquaredDistance;
236 pcl::PointXYZ search_point_tree;
237 search_point_tree.x=search_point_tree.y=search_point_tree.z=0;
238 if( kdtree.radiusSearch(search_point_tree, 10, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 ){
239 double before_w=10, temp_w;
241 temp_w =
sqrt(pointRadiusSquaredDistance[
index]);
242 if(temp_w - before_w > handle.finger_w*2){
247 if(before_w < min_width){
248 min_theta_index = theta_;
249 min_width = before_w;
254 geometry_msgs::Point temp_point;
255 std_msgs::ColorRGBA temp_color;
256 temp_color.r=0; temp_color.g=0; temp_color.b=1; temp_color.a=1;
257 temp_point.x=
x-temp_mat.
getColumn(1)[0] * before_w;
258 temp_point.y=
y-temp_mat.
getColumn(1)[1] * before_w;
259 temp_point.z=
z-temp_mat.
getColumn(1)[2] * before_w;
260 debug_hand_marker.points.push_back(temp_point);
261 debug_hand_marker.colors.push_back(temp_color);
262 temp_point.x+=2*temp_mat.
getColumn(1)[0] * before_w;
263 temp_point.y+=2*temp_mat.
getColumn(1)[1] * before_w;
264 temp_point.z+=2*temp_mat.
getColumn(1)[2] * before_w;
265 debug_hand_marker.points.push_back(temp_point);
266 debug_hand_marker.colors.push_back(temp_color);
269 geometry_msgs::PoseStamped handle_pose_stamped;
270 handle_pose_stamped.header = cloud_msg->header;
271 handle_pose_stamped.pose.position.x =
x;
272 handle_pose_stamped.pose.position.y =
y;
273 handle_pose_stamped.pose.position.z =
z;
274 handle_pose_stamped.pose.orientation.x = min_qua.getX();
275 handle_pose_stamped.pose.orientation.y = min_qua.getY();
276 handle_pose_stamped.pose.orientation.z = min_qua.getZ();
277 handle_pose_stamped.pose.orientation.w = min_qua.
getW();
278 std_msgs::Float64 min_width_msg;
279 min_width_msg.data = min_width;
281 pub_debug_marker_.publish(debug_hand_marker);
283 jsk_recognition_msgs::SimpleHandle simple_handle;
284 simple_handle.header = handle_pose_stamped.header;
285 simple_handle.pose = handle_pose_stamped.pose;
286 simple_handle.handle_width = min_width;
287 pub_handle_.publish(simple_handle);