00001
00002
00003 import numpy as np
00004
00005 import rospy
00006 import sensor_msgs.point_cloud2 as pc2
00007 import tf.transformations
00008
00009 from geometry_msgs.msg import Pose, PoseArray
00010 from jsk_topic_tools import ConnectionBasedTransport
00011 from sensor_msgs.msg import PointCloud2
00012 from sklearn.decomposition import PCA
00013
00014 class DetectGraspablePosesPcabase(ConnectionBasedTransport):
00015
00016 def __init__(self):
00017
00018 rospy.logwarn("This node is experiential one.")
00019
00020 super(DetectGraspablePosesPcabase, self).__init__()
00021
00022 self.direction = rospy.get_param('~direction', 'x')
00023 self.hand_size = rospy.get_param('~hand_size', 0.13)
00024 self.interval_m = rospy.get_param('~interval_m', '0.04')
00025
00026 self.pub_target_poses = self.advertise("~output/can_grasp_poses", PoseArray, queue_size=1)
00027
00028 def subscribe(self):
00029 rospy.Subscriber('~input', PointCloud2, self.callback)
00030
00031 def unsubscribe(self):
00032 self.sub.unregister()
00033
00034 def callback(self, point_cloud):
00035
00036 points = np.array(list(pc2.read_points(point_cloud, skip_nans=True)))
00037
00038 interval_m = self.interval_m
00039
00040 if self.direction == 'z':
00041 points_surface = points[:, [0, 1]]
00042 elif self.direction == 'x':
00043 points_surface = points[:, [1, 2]]
00044 else:
00045 rospy.logwarn("direction should be x or z")
00046
00047 pca = PCA(n_components=2)
00048 pca.fit(points_surface)
00049 new_points = pca.transform(points_surface)
00050 new_points = new_points[np.argsort(new_points[:, 0])]
00051
00052 min_x = new_points[0, 0]
00053 max_x = new_points[-1, 0]
00054
00055 discrete_xy_list = []
00056
00057 while min_x <= max_x:
00058 candidate = new_points[np.where(new_points[:, 0] < (min_x + interval_m))]
00059 new_points = new_points[np.where(new_points[:, 0] >= (min_x + interval_m))]
00060 if len(candidate) > 0:
00061 mean_x = np.mean(candidate, axis=0)[0]
00062 mean_y = np.mean(candidate, axis=0)[1]
00063 range_y = np.max(candidate[:, 1]) - np.min(candidate[:, 1])
00064 discrete_xy_list.append([mean_x, mean_y, range_y])
00065 min_x += interval_m
00066
00067 discrete_xy_list = np.array(discrete_xy_list)
00068 discrete_xy_list = discrete_xy_list[np.where(discrete_xy_list[:, 2] < self.hand_size)]
00069 discrete_xy_list = discrete_xy_list[np.argsort(np.absolute(discrete_xy_list[:, 0]))]
00070 grasp_xy_list = pca.inverse_transform(discrete_xy_list[:, [0, 1]])
00071
00072 search_range_m = interval_m
00073
00074 grasp_position_list = []
00075
00076 for grasp_xy in grasp_xy_list:
00077 if self.direction == 'z':
00078 points_depth = points[np.where((points[:, 0] > grasp_xy[0] - search_range_m) &
00079 (points[:, 0] < grasp_xy[0] + search_range_m) &
00080 (points[:, 1] > grasp_xy[1] - search_range_m) &
00081 (points[:, 1] < grasp_xy[1] + search_range_m))]
00082 points_depth = points_depth[:, 2]
00083 elif self.direction == 'x':
00084 points_depth = points[np.where((points[:, 1] > grasp_xy[0] - search_range_m) &
00085 (points[:, 1] < grasp_xy[0] + search_range_m) &
00086 (points[:, 2] > grasp_xy[1] - search_range_m) &
00087 (points[:, 2] < grasp_xy[1] + search_range_m))]
00088 points_depth = points_depth[:, 0]
00089 else:
00090 rospy.logwarn("direction should be x or z")
00091 if len(points_depth) > 0:
00092 grasp_position = np.append(grasp_xy, np.mean(points_depth))
00093 else:
00094 rospy.logwarn("it happens that something wrong")
00095 grasp_position_list.append(list(grasp_position))
00096
00097 pub_msg = PoseArray()
00098 pub_msg.header = point_cloud.header
00099
00100 trans_matrix = tf.transformations.identity_matrix()
00101 if self.direction == 'z':
00102 trans_matrix[0, 0] = 0
00103 trans_matrix[1, 0] = 0
00104 trans_matrix[2, 0] = -1
00105 trans_matrix[0, 1] = -1 * pca.components_[0, 1]
00106 trans_matrix[1, 1] = pca.components_[0, 0]
00107 trans_matrix[0, 2] = pca.components_[0, 0]
00108 trans_matrix[1, 2] = pca.components_[0, 1]
00109 trans_matrix[2, 2] = 0
00110
00111 elif self.direction == 'x':
00112
00113 if pca.components_[0, 0] > 0:
00114 trans_matrix[1, 1] = pca.components_[0, 0]
00115 trans_matrix[2, 1] = pca.components_[0, 1]
00116 trans_matrix[1, 2] = -1 * pca.components_[0, 1]
00117 trans_matrix[2, 2] = pca.components_[0, 0]
00118 else:
00119 trans_matrix[1, 1] = -1 * pca.components_[0, 0]
00120 trans_matrix[2, 1] = -1 * pca.components_[0, 1]
00121 trans_matrix[1, 2] = pca.components_[0, 1]
00122 trans_matrix[2, 2] = -1 * pca.components_[0, 0]
00123 else:
00124 rospy.logwarn("direction should be x or z")
00125
00126 quaternion = tf.transformations.quaternion_from_matrix(trans_matrix)
00127
00128 for grasp_position in grasp_position_list:
00129 pose = Pose()
00130 if self.direction == 'z':
00131 pose.position.x = grasp_position[0]
00132 pose.position.y = grasp_position[1]
00133 pose.position.z = grasp_position[2]
00134 elif self.direction == 'x':
00135 pose.position.x = grasp_position[2]
00136 pose.position.y = grasp_position[0]
00137 pose.position.z = grasp_position[1]
00138 else:
00139 rospy.logwarn("direction should x or z")
00140 pose.orientation.x = quaternion[0]
00141 pose.orientation.y = quaternion[1]
00142 pose.orientation.z = quaternion[2]
00143 pose.orientation.w = quaternion[3]
00144 pub_msg.poses.append(pose)
00145
00146 self.pub_target_poses.publish(pub_msg)
00147
00148 if __name__ == '__main__':
00149 rospy.init_node('detect_graspable_poses_pcabase')
00150 DetectGraspablePosesPcabase()
00151 rospy.spin()