Skip to content

A repo for implementing a statistical outlier removal filter on a pointcloud data in ROS2 and python

License

Notifications You must be signed in to change notification settings

AbubakarAliyuBadawi/Lidar_ICP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 

Repository files navigation

LiDAR Point Cloud Registration Algorithm Implementation

Algorithm Overview

This implementation performs real-time point cloud registration using Iterative Closest Point (ICP) algorithm in ROS. The algorithm processes sequential LiDAR frames to maintain spatial alignment and track sensor movement over time.

Core Algorithm Components

1. Point Cloud Preprocessing

The algorithm starts with preprocessing each incoming point cloud frame:

def filter_cloud(self, cloud_pcl):
    # Voxel Grid Downsampling
    # Reduces point cloud density uniformly to improve processing speed
    vg = cloud_pcl.make_voxel_grid_filter()
    vg.set_leaf_size(0.2, 0.2, 0.2)  # 20cm cubic voxels
    filtered = vg.filter()
    
    # Statistical Outlier Removal
    # Removes noise and outlier points
    sor = filtered.make_statistical_outlier_filter()
    sor.set_mean_k(30)                # Analyzes 30 nearest neighbors
    sor.set_std_dev_mul_thresh(2.0)   # Points outside 2 standard deviations are removed
    filtered = sor.filter()

2. ICP Registration Process

The core ICP alignment is performed between consecutive frames:

def perform_icp(self, source_cloud, target_cloud):
    icp = source_cloud.make_IterativeClosestPoint()
    
    # ICP parameters:
    # - Max correspondence distance: 0.5m
    # - Max iterations: 50
    # - Convergence epsilon: 1e-6
    
    converged, transform, estimate, fitness = icp.icp(source_cloud, target_cloud)

The ICP process iteratively:

  1. Finds closest point pairs between source and target clouds
  2. Estimates transformation to minimize distance between pairs
  3. Applies transformation and repeats until convergence

3. Transform Validation

All computed transformations undergo validation to ensure physical realism:

def check_transform_validity(self, transform):
    # Translation Check
    # Maximum allowed movement between frames: 5.0 meters
    translation = transform[:3, 3]
    translation_magnitude = np.linalg.norm(translation)
    
    # Rotation Check
    # Maximum allowed rotation between frames: 1.0 radians (~57 degrees)
    rotation = transform[:3, :3]
    euler_angles = tf.transformations.euler_from_matrix(rotation)
    max_rotation = max(abs(angle) for angle in euler_angles)

4. Point Cloud Transformation

After validation, points are transformed to the fixed frame:

def transform_cloud(self, cloud_pcl, transform):
    points = np.asarray(cloud_pcl)
    transformed_points = []
    
    # Apply 4x4 transformation matrix to each point
    for point in points:
        p = np.array([point[0], point[1], point[2], 1.0])
        transformed = np.dot(transform, p)
        transformed_points.append(transformed[:3])

Processing Pipeline

Frame-to-Frame Processing

The main callback processes each new frame through the following steps:

  1. Initial Frame Handling

    if self.previous_cloud is None:
        self.previous_cloud = current_filtered
        self.accumulated_points = points_list
    • First frame becomes reference frame
    • Establishes initial coordinate system
  2. Subsequent Frame Processing

    # Perform ICP with previous frame
    success, transform, message = self.perform_icp(current_filtered, self.previous_cloud)
    
    # Update cumulative transform
    self.cumulative_transform = np.dot(self.cumulative_transform, transform)
    
    # Transform current points to fixed frame
    transformed_cloud = self.transform_cloud(current_filtered, self.cumulative_transform)
  3. Point Accumulation

    # Add transformed points to accumulated cloud
    transformed_points = transformed_cloud.to_array().tolist()
    self.accumulated_points.extend(transformed_points)

Quality Control Measures

  1. Registration Quality

    • Minimum fitness score threshold: 0.01
    • Convergence checking in ICP
    if fitness < self.min_fitness_score:
        return False, None, f"Poor alignment score: {fitness}"
  2. Motion Constraints

    • Maximum translation: 5.0 meters
    • Maximum rotation: 1.0 radians
    • Prevents physically impossible transformations

Algorithm Parameters

ICP Parameters

  • max_correspondence_distance = 0.5 # Maximum point pair distance
  • max_iterations = 50 # ICP iteration limit
  • fitness_epsilon = 1e-6 # Convergence threshold

Filtering Parameters

  • leaf_size = 0.2 # Voxel grid size
  • min_fitness_score = 0.01 # Minimum acceptable alignment quality

Motion Limits

  • max_translation = 5.0 # Maximum movement between frames
  • max_rotation = 1.0 # Maximum rotation between frames

Error Handling

  1. Empty Point Clouds

    if not points_list:
        rospy.logwarn("Empty point cloud received")
        return
  2. ICP Failure

    if not converged:
        return False, None, "ICP failed to converge"
  3. Transform Validation

    valid_transform, message = self.check_transform_validity(transf)
    if not valid_transform:
        return False, None, message

This implementation ensures robust point cloud registration through careful preprocessing, validation, and error checking while maintaining alignment accuracy through cumulative transform updates.

About

A repo for implementing a statistical outlier removal filter on a pointcloud data in ROS2 and python

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published