Exemple #1
0
def ransac_render(cloud):

    pointCloud = vpc.VtkPointCloud()
    model_p = pcl.SampleConsensusModelPlane(cloud)
    ransac = pcl.RandomSampleConsensus(model_p)
    ransac.set_DistanceThreshold(1)
    ransac.computeModel()
    plane = ransac.get_Inliers()
    print(len(plane))

    find_plane = 0  ## index of inlier inside cloud
    cnt = 0
    for i in range(0, cloud.size):
        plane_index = plane[find_plane]
        if plane_index == i:
            if find_plane < len(plane) - 1:
                find_plane += 1
        else:
            pointCloud.addPoint(cloud[i], -1)
            cnt += 1
    print(cnt)
    print(cloud.size)
    renderer = vtk.vtkRenderer()
    renderWindow = vtk.vtkRenderWindow()
    renderWindow.AddRenderer(renderer)
    renderWindowInteractor = vtk.vtkRenderWindowInteractor()
    renderWindowInteractor.SetRenderWindow(renderWindow)
    renderer.AddActor(pointCloud.point_vtkActor)
    renderer.SetBackground(0.0, 0.0, 0.0)
    renderWindow.Render()
    renderWindowInteractor.Initialize()
    renderWindowInteractor.Start()
Exemple #2
0
def ransac(cloud):
    model_p = pcl.SampleConsensusModelPlane(cloud)
    ransac = pcl.RandomSampleConsensus(model_p)
    ransac.set_DistanceThreshold(0.1)
    ransac.computeModel()
    plane = ransac.get_Inliers()

    final = []
    find_plane = 0  ## index of inlier inside cloud
    for i in range(0, cloud.size):
        plane_index = plane[find_plane]
        if plane_index == i:
            if find_plane < len(plane) - 1:
                find_plane += 1
        else:
            final.append(cloud[i])

    return pcl.PointCloud(final)
    def test_ModelPlane(self):
        model_p = pcl.SampleConsensusModelPlane(self.p)
        ransac = pcl.RandomSampleConsensus(model_p)
        ransac.set_DistanceThreshold(.01)
        ransac.computeModel()
        inliers = ransac.get_Inliers()

        # print(str(len(inliers)))
        self.assertNotEqual(len(inliers), 0)

        final = pcl.PointCloud()

        if len(inliers) != 0:
            finalpoints = np.zeros((len(inliers), 3), dtype=np.float32)

            for i in range(0, len(inliers)):
                finalpoints[i][0] = self.p[inliers[i]][0]
                finalpoints[i][1] = self.p[inliers[i]][1]
                finalpoints[i][2] = self.p[inliers[i]][2]

            final.from_array(finalpoints)

        self.assertNotEqual(final.size, 0)
        pass
Exemple #4
0
def ModelPlane(cloud_filter, threshold=0.1, ext=True):
    modle_p = pcl.SampleConsensusModelPlane(cloud_filter)
    ransac = pcl.RandomSampleConsensus(modle_p)
    ransac.set_DistanceThreshold(threshold)
    ransac.computeModel()
    # ransac.setNegative(True)
    inliers = ransac.get_Inliers()
    # final.extract()
    final = pcl.PointCloud()
    finalpoints = np.zeros((len(inliers), 3), dtype=np.float32)

    for i in range(0, len(inliers)):
        finalpoints[i][0] = cloud_filter[inliers[i]][0]
        finalpoints[i][1] = cloud_filter[inliers[i]][1]
        finalpoints[i][2] = cloud_filter[inliers[i]][2]
    # finalpoints[1][0] = cloud_filter[inliers[1]][0]
    # finalpoints[1][1] = cloud_filter[inliers[1]][1]
    # finalpoints[1][2] = cloud_filter[inliers[1]][2]
    final = pcl.PointCloud()
    final.from_array(finalpoints)
    if ext == True:
        return cloud_filter.extract(inliers, True)
    else:
        return final
Exemple #5
0
    def extract_points_3D(self, pointcloud_msg, now, proc_results, calibrator_instance):
        # print("lidar_points:", len(lidar_points), ":", [x.shape for x in lidar_points])
        # Log PID
        rospy.loginfo('3D Picker PID: [%d]' % os.getpid())

        # Extract points data
        points = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud_msg)
        points = np.asarray(points.tolist())
        if (len(points.shape)>2):
            points = points.reshape(-1, points.shape[-1])
        points = points[~np.isnan(points).any(axis=1), :]
        points2pcd(points, os.path.join(PKG_PATH, CALIB_PATH, self.camera_name+"_pcd", str(self.lidar_points_num)+".pcd"))
        if (self.args.transform_pointcloud):
            points = (self.lidar_rotation_matrix.dot(points[:,:3].T) + self.lidar_translation_vector.reshape(-1,1)).T

        # Select points within chessboard range
        inrange = np.where((np.abs(points[:, 0]) < 7) &
                        (points[:, 1] < 25) &
                        (points[:, 1] > 0) &
                        # (points[:, 2] < 4) &
                        (points[:, 2] > 0.2))
        points = points[inrange[0]]
        if points.shape[0] < 10:
            rospy.logwarn('Too few PCL points available in range')
            return

        # pptk viewer
        viewer = pptk.viewer(points[:, :3])
        viewer.set(lookat=(0,0,4))
        viewer.set(phi=-1.57)
        viewer.set(theta=0.4)
        viewer.set(r=4)
        viewer.set(floor_level=0)
        viewer.set(point_size=0.02)
        rospy.loginfo("Press [Ctrl + LeftMouseClick] to select a chessboard point. Press [Enter] on viewer to finish selection.")
        pcl_pointcloud = pcl.PointCloud(points[:,:3].astype(np.float32))
        region_growing = pcl_pointcloud.make_RegionGrowing(searchRadius=self.chessboard_diagonal/5.0)
        indices = []
        viewer.wait()
        indices = viewer.get('selected')
        if (len(indices) < 1):
            rospy.logwarn("No point selected!")
            # self.terminate_all()
            viewer.close()
            return
        rg_indices = region_growing.get_SegmentFromPoint(indices[0])
        points_color = np.zeros(len(points))
        points_color[rg_indices] = 1
        viewer.attributes(points_color)
        # viewer.wait()
        chessboard_pointcloud = pcl_pointcloud.extract(rg_indices)
        plane_model = pcl.SampleConsensusModelPlane(chessboard_pointcloud)
        pcl_RANSAC = pcl.RandomSampleConsensus(plane_model)
        pcl_RANSAC.set_DistanceThreshold(0.01)
        pcl_RANSAC.computeModel()
        inliers = pcl_RANSAC.get_Inliers()
        # random select a fixed number of lidar points to reduce computation time
        inliers = np.random.choice(inliers, self.args.lidar_points)
        chessboard_points = np.asarray(chessboard_pointcloud)
        proc_results.put([np.asarray(chessboard_points[inliers, :3])])
        points_color = np.zeros(len(chessboard_points))
        points_color[inliers] = 1
        viewer.load(chessboard_points[:,:3])
        viewer.set(lookat=(0,0,4))
        viewer.set(phi=-1.57)
        viewer.set(theta=0.4)
        viewer.set(r=2)
        viewer.set(floor_level=0)
        viewer.set(point_size=0.02)
        viewer.attributes(points_color)
        viewer.attributes(points_color)
        rospy.loginfo("Check the chessboard segmentation in the viewer.")
        viewer.wait()
        viewer.close()
# pcl::RandomSampleConsensus<pcl::PointXYZ> ransac (model_p);
# ransac.setDistanceThreshold (.01);
# ransac.computeModel();
# ransac.getInliers(inliers);
# }
# else if (pcl::console::find_argument (argc, argv, "-sf") >= 0 )
# {
# pcl::RandomSampleConsensus<pcl::PointXYZ> ransac (model_s);
# ransac.setDistanceThreshold (.01);
# ransac.computeModel();
# ransac.getInliers(inliers);
# }
###
# inliers = vector[int]
model_s = pcl.SampleConsensusModelSphere(cloud)
model_p = pcl.SampleConsensusModelPlane(cloud)
if argc > 1:
    if argvs == "-f":
        ransac = pcl.RandomSampleConsensus(model_p)
        ransac.set_DistanceThreshold(.01)
        ransac.computeModel()
        inliers = ransac.get_Inliers()
    elif argvs == "-sf":
        ransac = pcl.RandomSampleConsensus(model_s)
        ransac.set_DistanceThreshold(.01)
        ransac.computeModel()
        inliers = ransac.get_Inliers()
    else:
        inliers = []
else:
    inliers = []
    def extract_points_3D(self, pcd_file, proc_results):
        # print("lidar_points:", len(lidar_points), ":", [x.shape for x in lidar_points])
        # Log PID
        rospy.loginfo('3D Picker PID: [%d] file name: %s' %
                      (os.getpid(), os.path.basename(pcd_file)))

        # Extract points data
        points = pcl.load(pcd_file).to_array()
        # Select points within chessboard range
        inrange = np.where((np.abs(points[:, 0]) < 8) & (points[:, 1] < 25)
                           & (points[:, 1] > 0) &
                           # (points[:, 2] < 4) &
                           (points[:, 2] > 0.2))
        points = points[inrange[0]]
        if points.shape[0] < 10:
            rospy.logwarn('Too few PCL points available in range')
            return

        # pptk viewer
        viewer = pptk.viewer(points[:, :3])
        viewer.set(lookat=(0, 0, 4))
        viewer.set(phi=-1.57)
        viewer.set(theta=0.4)
        viewer.set(r=4)
        viewer.set(floor_level=0)
        viewer.set(point_size=0.02)
        rospy.loginfo(
            "Press [Ctrl + LeftMouseClick] to select a chessboard point. Press [Enter] on viewer to finish selection."
        )
        pcl_pointcloud = pcl.PointCloud(points[:, :3].astype(np.float32))
        region_growing = pcl_pointcloud.make_RegionGrowing(
            searchRadius=self.chessboard_diagonal / 5.0)
        indices = []
        viewer.wait()
        indices = viewer.get('selected')
        if (len(indices) < 1):
            rospy.logwarn("No point selected! Skip this frame.")
            viewer.close()
            return
        rg_indices = region_growing.get_SegmentFromPoint(indices[0])
        points_color = np.zeros(len(points))
        points_color[rg_indices] = 1
        viewer.attributes(points_color)
        # viewer.wait()
        chessboard_pointcloud = pcl_pointcloud.extract(rg_indices)
        plane_model = pcl.SampleConsensusModelPlane(chessboard_pointcloud)
        pcl_RANSAC = pcl.RandomSampleConsensus(plane_model)
        pcl_RANSAC.set_DistanceThreshold(0.01)
        pcl_RANSAC.computeModel()
        inliers = pcl_RANSAC.get_Inliers()
        inliers = np.random.choice(inliers, self.args.lidar_points)
        chessboard_points = np.asarray(chessboard_pointcloud)
        proc_results.put([np.asarray(chessboard_points[inliers, :3])])
        points_color = np.zeros(len(chessboard_points))
        points_color[inliers] = 1
        viewer.load(chessboard_points[:, :3])
        viewer.set(lookat=(0, 0, 4))
        viewer.set(phi=-1.57)
        viewer.set(theta=0.4)
        viewer.set(r=2)
        viewer.set(floor_level=0)
        viewer.set(point_size=0.02)
        viewer.attributes(points_color)
        rospy.loginfo("Check the chessboard segmentation in the viewer.")
        viewer.wait()
        viewer.close()
def calibrate(points3D=None):
    # Load corresponding points
    folder = os.path.join(PKG_PATH, CALIB_PATH)
    if points3D is None and os.path.exists(
            os.path.join(folder, 'lidar_points.txt')):
        points3D = np.loadtxt(os.path.join(folder, 'lidar_points.txt'))

    # print("points3D:", points3D.shape)

    # Estimate extrinsics
    # best-fit linear plane

    # method 1: PCA method
    # pca = PCA()
    # pca.fit(points3D[:,:3])
    # normal_vector = pca.components_[2]

    # method 2: lstsq method
    # A = np.c_[points3D[:,0], points3D[:,1], np.ones(points3D.shape[0])]
    # C,_,_,_ = scipy.linalg.lstsq(A, points3D[:,2])    # coefficients
    # # evaluate it on grid
    # # Z = C[0]*X + C[1]*Y + C[2]
    # # or expressed using matrix/vector product
    # #Z = np.dot(np.c_[XX, YY, np.ones(XX.shape)], C).reshape(X.shape)
    # # normal vector
    # # print("C:", C)
    # normal_vector = np.array([C[0], C[1], -1])
    # normal_vector = np.array(normal_vector) / np.linalg.norm(normal_vector)
    # translation_vector = np.array([[0],[0],[C[2]]]) # shpae: (3,1)

    # method 3: PCL RANSAC fit plane
    pcl_pointcloud = pcl.PointCloud(points3D[:, :3].astype(np.float32))
    plane_model = pcl.SampleConsensusModelPlane(pcl_pointcloud)
    pcl_RANSAC = pcl.RandomSampleConsensus(plane_model)
    pcl_RANSAC.set_DistanceThreshold(0.03)
    pcl_RANSAC.computeModel()
    inliers = pcl_RANSAC.get_Inliers()
    points3D = points3D[inliers, :3]
    pca = PCA()
    pca.fit(points3D)
    normal_vector = pca.components_[2]
    translation_vector = np.zeros((3, 1))

    if (normal_vector[2] < 0): normal_vector = -normal_vector
    # print("normal vector:", normal_vector)
    # rotation_angle = np.arccos(normal_vector[2])
    # rotation_vector_temp = np.cross(normal_vector, np.array([0,0,1]))
    # rotation_vector = rotation_angle * rotation_vector_temp / np.linalg.norm(rotation_vector_temp)

    # Convert rotation vector
    rotation_matrix = rotation_matrix_from_vectors(normal_vector,
                                                   np.array([0, 0, 1]))
    euler = euler_from_matrix(rotation_matrix)
    # use reverse transform because of issues in the BIT-IVRC sensor_driver package
    reverse_euler_angles = np.zeros((1, 3))
    reverse_rotation_matrix = rotation_matrix_from_vectors(
        np.array([0, 0, 1]), normal_vector)
    reverse_euler_angles = euler_from_matrix(reverse_rotation_matrix)
    alfa, beta, gama = reverse_euler_angles
    alfa = -alfa
    # x_offset, y_offset, z_offset = C
    transform_matrix_calibration = np.zeros((3, 3))
    transform_matrix_calibration[0, 0] = np.cos(beta) * np.cos(gama) - np.sin(
        beta) * np.sin(alfa) * np.sin(gama)
    transform_matrix_calibration[1, 0] = np.cos(beta) * np.sin(gama) + np.sin(
        beta) * np.sin(alfa) * np.cos(gama)
    transform_matrix_calibration[2, 0] = -np.cos(alfa) * np.sin(beta)

    transform_matrix_calibration[0, 1] = -np.cos(alfa) * np.sin(gama)
    transform_matrix_calibration[1, 1] = np.cos(alfa) * np.cos(gama)
    transform_matrix_calibration[2, 1] = np.sin(alfa)

    transform_matrix_calibration[0, 2] = np.sin(beta) * np.cos(gama) + np.cos(
        beta) * np.sin(alfa) * np.sin(gama)
    transform_matrix_calibration[1, 2] = np.sin(beta) * np.sin(gama) - np.cos(
        beta) * np.sin(alfa) * np.cos(gama)
    transform_matrix_calibration[2, 2] = np.cos(alfa) * np.cos(beta)

    # points3D = np.matmul(points3D[:,:3], transform_matrix_calibration)
    points3D = transform_matrix_calibration.dot(points3D[:, :3].T).T
    z_mean = np.mean(points3D[:, 2])
    # print("Z statitics:", z_mean, np.std(points3D[:,2]))
    # viewer = pptk.viewer(points3D[:,:3])
    # viewer.wait()
    translation_vector[2] = -z_mean
    rospy.loginfo(
        "The following values are used for tf static_transform_publisher")
    # print("rotation_matrix * normal_vector:", np.dot(rotation_matrix, normal_vector))
    # print("rotation_matrix * [0,0,1]:", np.dot(rotation_matrix, np.array([0,0,1])))
    # Display results
    print('Euler angles (RPY):', euler)
    print('Rotation Matrix:', rotation_matrix)
    print('Translation Offsets:', translation_vector)

    # Save extrinsics
    if (not os.path.exists(folder)):
        os.makedirs(folder)
    np.savez(os.path.join(folder, args.lidar_name + '_extrinsics.npz'),
             euler=euler,
             R=rotation_matrix,
             T=translation_vector)
    # with open(os.path.join(folder, args.lidar_name + '_extrinsics.yaml'),'w') as f:
    #     yaml.dump({'euler':list(euler), 'R':rotation_matrix.tolist(), 'T':translation_vector.tolist()},f)

    calibration_string = lidarCalibrationYamlBuf(rotation_matrix,
                                                 translation_vector,
                                                 euler,
                                                 name=args.lidar_name)
    if (not os.path.exists(folder)):
        os.mkdir(folder)
    with open(os.path.join(folder, args.lidar_name + '_extrinsics.yaml'),
              'w') as f:
        f.write(calibration_string)

    reverse_euler_angles = np.array(reverse_euler_angles)
    reverse_euler_angles *= 180. / np.pi
    rospy.loginfo(
        "Calibration finished. Copy the following offsets and angles to the lua file in sensor_driver package."
    )
    rospy.loginfo(
        "x_offset: %f, y_offset: %f, z_offset: %f" %
        (translation_vector[0], translation_vector[1], translation_vector[2]))
    rospy.loginfo("x_angle: %f, y_angle: %f, z_angle: %f" %
                  (-reverse_euler_angles[0], reverse_euler_angles[1],
                   reverse_euler_angles[2]))
    return reverse_rotation_matrix, transform_matrix_calibration, translation_vector