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()