10 import tf.transformations
11 from sensor_msgs.msg
import LaserScan
12 from sensor_msgs.msg
import PointCloud
13 from sensor_msgs.msg
import ChannelFloat32
14 from geometry_msgs.msg
import Point32
15 from geometry_msgs.msg
import PoseStamped
19 min_detect_angle = -0.87266
20 max_detect_angle = 0.87266
23 cluster_threshold = 0.04
24 icp_distance_threshold = 0.01
25 potential_clouds_min_points = 80
28 dock_pose = PoseStamped()
29 dock_pointcloud = PointCloud()
30 cluster_pointcloud = PointCloud()
31 ideal_dock_pointcloud = PointCloud()
34 np_points = np.ones((len(points), 3))
35 for i
in range(len(points)):
36 np_points[i][0] = points[i].x
37 np_points[i][1] = points[i].y
38 np_points[i][2] = points[i].z
45 global ideal_dock_pointcloud
50 hypotenuse_length = 0.14
51 base_angle = math.pi / 3.0 * 2.0
53 base_points_count = points_count/4*2 + points_count%4
54 hypotenuse_points_count = points_count / 4
56 base_step_delta = base_length / base_points_count
57 hypotenuse_delta_x = math.sin(base_angle) * hypotenuse_length / hypotenuse_points_count
58 hypotenuse_delta_y = math.cos(base_angle) * hypotenuse_length / hypotenuse_points_count
63 for i
in range(hypotenuse_points_count):
65 point.x = hypotenuse_delta_x * (hypotenuse_points_count-i) * (-1)
66 point.y = -(base_length/2.0) + hypotenuse_delta_y*(hypotenuse_points_count-i)
68 ideal_dock_cloud.append(point)
71 for i
in range(base_points_count):
72 point = Point32(0.0, base_length/2.0-i*base_step_delta, 0.0)
73 ideal_dock_cloud.append(point)
76 for i
in range(hypotenuse_points_count):
78 point.x = hypotenuse_delta_x * (hypotenuse_points_count-i) * (-1)
79 point.y = (base_length/2.0) - hypotenuse_delta_y*(hypotenuse_points_count-i)
81 ideal_dock_cloud.append(point)
84 ideal_dock_pointcloud = PointCloud()
85 ideal_dock_pointcloud.header.frame_id =
"dock" 86 ideal_dock_pointcloud.header.stamp = rospy.Time.now()
88 ideal_dock_pointcloud.points = ideal_dock_cloud
90 return ideal_dock_cloud
93 global cluster_pointcloud, dock_pose, T, find_dock
94 angle_min = data.angle_min
95 angle_max = data.angle_max
96 angle_increment = data.angle_increment
102 last_point = Point32()
106 potential_clouds = []
108 for i
in xrange(len(data.ranges)):
109 if (angle_min + i * angle_increment) >= min_detect_angle
and (angle_min + i * angle_increment) <= max_detect_angle:
111 point.x = math.cos(angle_min + i * angle_increment) * data.ranges[i];
112 point.y = math.sin(angle_min + i * angle_increment) * data.ranges[i];
115 distance = math.sqrt(math.pow(point.x-last_point.x,2)+math.pow(point.y-last_point.y,2))
116 if(distance > cluster_threshold):
117 if(len(clouds)>potential_clouds_min_points):
118 potential_clouds.append(clouds)
124 last_range = data.ranges[i]
128 if(len(clouds)>potential_clouds_min_points):
129 potential_clouds.append(clouds)
131 if(len(potential_clouds)<=0):
137 best_distance = icp_distance_threshold
139 for p_i
in xrange(len(potential_clouds)):
145 T, distance, i =
icp.icp(ideal_dock_np, potential_cloud_np)
147 mean_distance = np.mean(distance)
148 if mean_distance < icp_distance_threshold:
149 if(mean_distance < best_distance):
151 best_distance = mean_distance
155 qt = tf.transformations.quaternion_from_matrix(best_T)
158 dock_pose = PoseStamped()
159 dock_pose.header.frame_id =
"laser_link" 160 dock_pose.header.stamp = rospy.Time.now()
161 dock_pose.pose.position.x = best_T[0][3]
162 dock_pose.pose.position.y = best_T[1][3]
163 dock_pose.pose.position.z = best_T[2][3]
164 dock_pose.pose.orientation.x = qt[0]
165 dock_pose.pose.orientation.y = qt[1]
166 dock_pose.pose.orientation.z = qt[2]
167 dock_pose.pose.orientation.w = qt[3]
174 cluster_pointcloud = PointCloud()
175 cluster_pointcloud.header = data.header
176 cluster_pointcloud.header.stamp = rospy.Time.now()
178 color_r = ChannelFloat32(
'rgb', [])
179 color_map = [0x00ff00, 0xffff00, 0xff00ff, 0x00ffff]
181 for i
in xrange(len(potential_clouds)):
182 for j
in xrange(len(potential_clouds[i])):
183 cluster_pointcloud.points.append(potential_clouds[i][j])
184 color_r.values.append(color_map[i%4])
186 cluster_pointcloud.channels.append(color_r)
189 global cluster_pointcloud, ideal_dock_pointcloud, T, find_dock, dock_pose
191 rospy.init_node(
'dock_detect', anonymous=
True)
193 rospy.Subscriber(
"scan", LaserScan, callback)
197 dock_pose_pub = rospy.Publisher(
'dock_pose', PoseStamped, queue_size=10)
198 dock_pointcloud_pub = rospy.Publisher(
'dock_pointcloud', PointCloud, queue_size=10)
199 cluster_pointcloud_pub = rospy.Publisher(
'cluster_pointcloud', PointCloud, queue_size=10)
201 cluster_pointcloud = PointCloud()
205 rate = rospy.Rate(40)
206 while not rospy.is_shutdown():
209 dock_tf_broadcaster.sendTransform(tf.transformations.translation_from_matrix(T), tf.transformations.quaternion_from_matrix(T), rospy.Time.now(),
"dock",
"laser_link")
214 dock_pose.header.stamp = rospy.Time.now()
217 dock_pose_pub.publish(dock_pose)
219 ideal_dock_pointcloud.header.stamp = rospy.Time.now()
220 dock_pointcloud_pub.publish(ideal_dock_pointcloud)
222 cluster_pointcloud.header.stamp = rospy.Time.now()
223 cluster_pointcloud_pub.publish(cluster_pointcloud)
227 if __name__ ==
'__main__':
def Point32ToNumpy(points)
def GenerateIdealDock(points_count)
def icp(A, B, init_pose=None, max_iterations=20, tolerance=0.001)