def pc2CB(self, msg): if self.init: print "---------------------" # Convert ROS PointCloud2 msg to PCL data cloud = pcl_helper.ros_to_pcl(msg) # Get transform of "base_link" relative to "map" trans = self.getTransform("map", "base_link") os1_trans = self.getTransform("map", "os1_sensor") # Filter the Cloud fil_cloud = filtering_helper.do_passthrough_filter(cloud, 'x', self.x_min, self.x_max) fil_cloud = filtering_helper.do_passthrough_filter(fil_cloud, 'y', self.y_min, self.y_max) fil_cloud = filtering_helper.do_passthrough_filter(fil_cloud, 'intensity', 330, 4096) # Turn XYZI cloud into XYZ cloud XYZ_cloud = pcl_helper.XYZI_to_XYZ(fil_cloud) # Statistical outlier filter fil = XYZ_cloud.make_statistical_outlier_filter() fil.set_mean_k(10) fil.set_std_dev_mul_thresh(0.1) filtered_cloud = fil.filter() pc2_msg = pcl_helper.pcl_to_ros(filtered_cloud, "base_link") self.pc2_pub.publish(pc2_msg) # Get groups of cluster of points clusters = self.getClusters(filtered_cloud, 0.05, 5, 350) print "len(clusters)", len(clusters) for i in range(0,len(clusters)): print "len(clusters[", i, "]", len(clusters[i]) # Get mean points from clusters mean_pts = [] for cluster in clusters: mean_pts.append(self.getMeanPoint(cluster, filtered_cloud)) print "len(mean_pts)", len(mean_pts) # for i in range(0,len(mean_pts)): # print "mean_pts[", i, "]", mean_pts[i] # Remove other points, leave the table points only table_pts = [] table_pts = self.getTablePoints(mean_pts) print "len(table_pts)", len(table_pts) # print table_pts for i in range(len(table_pts)): self.vizPoint(i, table_pts[i], ColorRGBA(1,1,1,1), "base_link") # Finding 2 middle points from 4 table legs and use them as path_pts path_pts = [] if(len(table_pts)==4): for p1 in table_pts: for p2 in table_pts: if(p1==p2): break # Register 2 middle_pts of 4 table legs if(0.73 < self.getDistance(p1, p2) < 0.83): path_pts.append(self.getMiddlePoint(p1, p2)) break # print "len(path_pts)", len(path_pts) # print path_pts # Turn path_pts into map frame for i in range(len(path_pts)): path_pts[i] = tf2_geometry_msgs.do_transform_pose(self.toPoseStamped(path_pts[i], Quaternion(0,0,0,1)), trans).pose.position path_pts[i] = Point(path_pts[i].x, path_pts[i].y, 0) # Record the starting point and heading once if self.record_once: # self.start_pt = trans.transform.translation self.start_pt = os1_trans.transform.translation self.record_once = False # Create a list with distance information between initial_pt and path_pts distance_list = [self.getDistance(p, self.start_pt) for p in path_pts] # Rearrange the path_pts to be in descending order path_pts = self.getDescend(path_pts, distance_list) # Duplicate the path_pts to prevent from being edited table_pathpts = path_pts[:] # print "table_pathpts: ", len(table_pathpts) if(len(table_pathpts)==2): # Get gradient of the Line of Best Fit m1 = self.getGradientLineOfBestFit(table_pathpts) # Insert another point on the line with d[m] away from the 2nd table_pathpts path_pts.append(self.getPointOnLine(m1, 1.0, table_pathpts[1], self.start_pt)) # Visualize the path_pts self.vizPoint(10, path_pts[0], ColorRGBA(1,0,0,1), "map") # Red self.vizPoint(11, path_pts[1], ColorRGBA(1,1,0,1), "map") # Yellow self.vizPoint(12, path_pts[2], ColorRGBA(1,0,1,1), "map") # Magenta # print len(path_pts) # Find the heading of the table (last 2 path_pts) heading_q = self.getOrientation(table_pathpts[0], table_pathpts[1]) # Publish the path self.route_pub.publish(self.getPath2Table(path_pts, heading_q))
def pc2CB(self, msg): if self.init: print "start_time", rospy.Time.now().to_sec() # Convert ROS PointCloud2 msg to PCL data cloud = pcl_helper.ros_to_pcl(msg) # Filter the Cloud fil_cloud = filtering_helper.do_passthrough_filter(cloud, 'x', self.x_min, self.x_max) filtered_cloud = filtering_helper.do_passthrough_filter(fil_cloud, 'y', self.y_min, self.y_max) # Turn cloud into colorless cloud # colorless_cloud = pcl_helper.XYZRGB_to_XYZ(filtered_cloud) colorless_cloud = pcl_helper.XYZI_to_XYZ(filtered_cloud) # Get groups of cluster of points # clusters = self.getClusters(colorless_cloud, 0.05, 20, 250) # Table on Top AGV - 60~230 clusters = self.getClusters(colorless_cloud, 0.05, 20, 350) # print "len(clusters)", len(clusters) # for i in range(0,len(clusters)): # print "len(clusters[", i, "]", len(clusters[i]) # Get mean points from clusters mean_pts = [] for cluster in clusters: mean_pts.append(self.getMeanPoint(cluster, filtered_cloud)) # print "len(mean_pts)", len(mean_pts) # for i in range(0,len(mean_pts)): # print "mean_pts[", i, "]", mean_pts[i] # Remove other points, leave the table points only table_pts = [] table_pts = self.getTablePoints(mean_pts) # print "len(table_pts)", len(table_pts) # print table_pts for i in range(len(table_pts)): self.vizPoint(i, table_pts[i], ColorRGBA(1,1,1,1), "base_link") # Get transform of "base_link" relative to "map" trans = self.getTransform("map", "base_link") # Finding 2 middle points from 4 table legs and use them as path_pts path_pts = [] if(len(table_pts)==4): for p1 in table_pts: for p2 in table_pts: if(p1==p2): break # Register 2 middle_pts of 4 table legs if(0.73 < self.getDistance(p1, p2) < 0.83): path_pts.append(self.getMiddlePoint(p1, p2)) break # print "len(path_pts)", len(path_pts) # print path_pts # Path_pts that generated from between 2 legs of table must be fulfill below requirement, else return if(len(path_pts)==2): if not (0.33 < self.getDistance(path_pts[0], path_pts[1]) < 0.48): return # Turn path_pts into map frame for i in range(len(path_pts)): path_pts[i] = tf2_geometry_msgs.do_transform_pose(self.toPoseStamped(path_pts[i], Quaternion(0,0,0,1)), trans).pose.position # Record the starting point once if self.record_once: self.start_pt = trans.transform.translation self.record_once = False # Create a list with distance information between initial_pt and path_pts distance_list = [self.getDistance(p, self.start_pt) for p in path_pts] # Rearrange the path_pts to be in ascending order path_pts = self.getAscend(path_pts, distance_list) # Duplicate the path_pts to prevent from being edited table_pathpts = path_pts[:] if(len(table_pathpts)==2): # Get gradient of the Line of Best Fit m1 = self.getGradientLineOfBestFit(table_pathpts) # Insert another point on the line with d[m] away from the 1st table_pathpts path_pts.insert(0, self.getPointOnLine(m1, 1.0, table_pathpts[0], self.start_pt)) # Insert a point ahead d[m] of table to the begin of path_pts # ahead_pt = self.getPointAheadTable(table_pathpts, 1.0) # path_pts.insert(0, ahead_pt) # Insert a point ahead d[m] of table to the middle of table_pathpts # midway_pt = self.getPointAheadTable(table_pathpts, -0.4) # path_pts.insert(2, midway_pt) # Insert another point on the line with d[m] away from the 1st table_pathpts # path_pts.insert(2, self.getPointOnLine(m1, 0.05, table_pathpts[1], self.start_pt)) # Remove the last point of path_pts # path_pts = path_pts[:len(path_pts)-1] # Add the AGV start_pt to the begin of path_pts # path_pts.insert(0, self.start_pt) # Visualize the path_pts # self.vizPoint(0, path_pts[0], ColorRGBA(1,0,0,1), "map") # Red # self.vizPoint(1, path_pts[1], ColorRGBA(1,1,0,1), "map") # Yellow # self.vizPoint(2, path_pts[2], ColorRGBA(0,0,1,1), "map") # Blue # Find the heading of the table (last 2 path_pts) heading_q = self.getOrientation(table_pathpts[0], table_pathpts[1]) # Publish the path self.route_pub.publish(self.getPath2Table(path_pts, heading_q)) # print "-----------------" print "end_time", rospy.Time.now().to_sec()
def pc2CB(self, msg): if self.init: self.start_time = rospy.Time.now().to_sec() print "-----------------" # Convert ROS PointCloud2 msg to PCL data cloud = pcl_helper.ros_to_pcl(msg) # Get transform of "base_link" relative to "map" trans = self.getTransform("map", "base_link") # Filter the Cloud fil_cloud = filtering_helper.do_passthrough_filter( cloud, 'x', self.x_min, self.x_max) fil_cloud = filtering_helper.do_passthrough_filter( fil_cloud, 'y', self.y_min, self.y_max) fil_cloud = filtering_helper.do_passthrough_filter( fil_cloud, 'intensity', 450, 4096) # Statistical outlier filter fil = pcl_helper.XYZI_to_XYZ( fil_cloud).make_statistical_outlier_filter() fil.set_mean_k(10) fil.set_std_dev_mul_thresh(0.05) #1.0 / 0.1 filtered_cloud = fil.filter() pc2_msg = pcl_helper.pcl_to_ros(filtered_cloud, "base_link") self.pc2_pub.publish(pc2_msg) # Get groups of cluster of points clusters = self.getClusters(filtered_cloud, 0.05, 10, 800) print "len(clusters)", len(clusters) for i in range(len(clusters)): print "clusters[" + str(i) + "]", len(clusters[i]) # Not enough clusters to be identified as charger unit if (len(clusters) < 3): return # self.middle_time_1 = rospy.Time.now().to_sec() # Extract charger_wall & charger_pillars clusters # - use for compute gradient of Line of Best Fit # - use for compute middle_pt wall_cluster, pillar_clusters = self.getChargerClusters( clusters, filtered_cloud) # self.middle_time_2 = rospy.Time.now().to_sec() # Cannot find the charger_wall and charger_pillars if (wall_cluster == None or pillar_clusters == []): print "wall cluster or pillar clusters not found" return print "wall_cluster", len(wall_cluster) self.vizPoint( 0, self.getMeanPointFromCluster(wall_cluster, filtered_cloud), ColorRGBA(0, 1, 0, 1), "base_link") for i in range(len(pillar_clusters)): print "pillar_clusters[" + str(i) + "]", len( pillar_clusters[i]) self.vizPoint( i + 1, self.getMeanPointFromCluster(pillar_clusters[i], filtered_cloud), ColorRGBA(0, 1, 0, 1), "base_link") # Get Points of wall_cluster wall_pts = self.getPointsFromCluster(wall_cluster, filtered_cloud) # Turn wall_pts into map frame for i in range(len(wall_cluster)): wall_pts[i] = tf2_geometry_msgs.do_transform_pose( self.toPoseStamped(wall_pts[i], Quaternion(0, 0, 0, 1)), trans).pose.position # Get gradient of the Line of Best Fit m1 = self.getGradientLineOfBestFit(wall_pts) print "gradient", m1 pillar_pts = [] # Get mean points from pillar_clusters for cluster in pillar_clusters: pillar_pts.append( self.getMeanPointFromCluster(cluster, filtered_cloud)) # Finding 1 middle_pt from 2 charger_pillars and use it as path_pts print pillar_pts if (len(pillar_pts) == 2): middle_pt = None for p1 in pillar_pts: for p2 in pillar_pts: if (p1 == p2): break # Only register middle_pt of 2 charger_pillars points if (0.5 < self.getDistance(p1, p2) < 0.65): middle_pt = self.getMiddlePoint(p1, p2) break if (middle_pt == None): "middle_pt not found" return # Turn middle_pt into map frame middle_pt = tf2_geometry_msgs.do_transform_pose( self.toPoseStamped(middle_pt, Quaternion(0, 0, 0, 1)), trans).pose.position # Register the middle_pt as one of the path_pts path_pts = [] path_pts.append(middle_pt) # Record the starting point and heading once if self.record_once: self.start_pt = trans.transform.translation self.record_once = False # Insert another point on the normal line with d[m] away from middle_pt path_pts.insert( 0, self.getPointOnNormalLine(m1, 1.5, middle_pt, self.start_pt)) # Duplicate the path points to prevent from being edited charger_pathpts = path_pts[:] # Insert another point on the normal line with d[m] away from middle_pt path_pts.insert(0, self.getPointOnNormalLine( m1, 0.29, middle_pt, self.start_pt)) #0.27 # Create a list with distance information between init_pt and path_pts distance_list = [ self.getDistance(p, self.start_pt) for p in path_pts ] # Rearrange the path_pts to be in ascending order path_pts = self.getAscend(path_pts, distance_list) # Add the AGV start_pt to the begin of path_pts # path_pts.insert(0, self.start_pt) # Remove last point of path_pts (middle pt of 2 charger feature pts) path_pts = path_pts[:len(path_pts) - 1] print "len(path_pts)", len(path_pts) # # Visualize the path_pts self.vizPoint(0, path_pts[0], ColorRGBA(1, 0, 0, 1), "map") # Red self.vizPoint(1, path_pts[1], ColorRGBA(1, 1, 0, 1), "map") # Yellow # self.vizPoint(2, path_pts[2], ColorRGBA(0,0,1,1), "map") # Blue # Find the heading of the charger (last 2 path_pts) heading_q = self.getOrientation(charger_pathpts[0], charger_pathpts[1]) # Publish the path self.route_pub.publish( self.getPath2Charger(path_pts, heading_q)) print "start_time", self.start_time # print "middle_time_1", self.middle_time_1 # print "middle_time_2", self.middle_time_2 print "end_time", rospy.Time.now().to_sec()