Example #1
0
    def construct_octree(self, open3d_point_cloud: open3d.geometry.PointCloud,
                         include_color: bool) -> torch.Tensor:

        # In case the point cloud has no points, add a single point
        # This is a workaround because I was not able to create an empty octree without getting a segfault
        # TODO: Figure out a better way of making an empty octree (it does not occur if setup correctly, so probably not worth it)
        if not open3d_point_cloud.has_points():
            open3d_point_cloud.points.append([
                (self._min_bound[0] + self._max_bound[0]) / 2,
                (self._min_bound[1] + self._max_bound[1]) / 2,
                (self._min_bound[2] + self._max_bound[2]) / 2
            ])
            open3d_point_cloud.normals.append([0.0, 0.0, 0.0])
            open3d_point_cloud.colors.append([0.0, 0.0, 0.0])

        # Convert open3d point cloud into octree points
        octree_points = conversions.open3d_point_cloud_to_octree_points(
            open3d_point_cloud, include_color)

        # Convert octree points into 1D Tensor (via ndarray)
        # Note: Copy of points here is necessary as ndarray would otherwise be immutable
        octree_points_ndarray = np.frombuffer(np.copy(octree_points.buffer()),
                                              np.uint8)
        octree_points_tensor = torch.from_numpy(octree_points_ndarray)

        # Finally, create an octree from the points
        return self._points_to_octree(octree_points_tensor)
Example #2
0
    def preprocess_point_cloud(
            self, open3d_point_cloud: open3d.geometry.PointCloud,
            camera_frame_id: str, robot_frame_id: str, min_bound: List[float],
            max_bound: List[float], normals_radius: float,
            normals_max_nn: int) -> open3d.geometry.PointCloud:

        # Check if any points remain in the area after cropping
        if not open3d_point_cloud.has_points():
            print("Point cloud has no points")
            return open3d_point_cloud

        # Get transformation from camera to robot and use it to transform point
        # cloud into robot's base coordinate frame
        transform = self.lookup_transform_sync(target_frame=robot_frame_id,
                                               source_frame=camera_frame_id)
        transform_mat = conversions.transform_to_matrix(transform=transform)
        open3d_point_cloud = open3d_point_cloud.transform(transform_mat)

        # Crop point cloud to include only the workspace
        open3d_point_cloud = open3d_point_cloud.crop(
            bounding_box=open3d.geometry.AxisAlignedBoundingBox(
                min_bound=min_bound, max_bound=max_bound))

        # Check if any points remain in the area after cropping
        if not open3d_point_cloud.has_points():
            print(
                "Point cloud has no points after cropping to the workspace volume"
            )
            return open3d_point_cloud

        # Estimate normal vector for each cloud point and orient these towards the camera
        open3d_point_cloud.estimate_normals(
            search_param=open3d.geometry.KDTreeSearchParamHybrid(
                radius=normals_radius, max_nn=normals_max_nn),
            fast_normal_computation=True)

        open3d_point_cloud.orient_normals_towards_camera_location(
            camera_location=transform_mat[0:3, 3])

        return open3d_point_cloud