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.
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()
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:
- Finds closest point pairs between source and target clouds
- Estimates transformation to minimize distance between pairs
- Applies transformation and repeats until convergence
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)
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])
The main callback processes each new frame through the following steps:
-
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
-
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)
-
Point Accumulation
# Add transformed points to accumulated cloud transformed_points = transformed_cloud.to_array().tolist() self.accumulated_points.extend(transformed_points)
-
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}"
-
Motion Constraints
- Maximum translation: 5.0 meters
- Maximum rotation: 1.0 radians
- Prevents physically impossible transformations
max_correspondence_distance = 0.5
# Maximum point pair distancemax_iterations = 50
# ICP iteration limitfitness_epsilon = 1e-6
# Convergence threshold
leaf_size = 0.2
# Voxel grid sizemin_fitness_score = 0.01
# Minimum acceptable alignment quality
max_translation = 5.0
# Maximum movement between framesmax_rotation = 1.0
# Maximum rotation between frames
-
Empty Point Clouds
if not points_list: rospy.logwarn("Empty point cloud received") return
-
ICP Failure
if not converged: return False, None, "ICP failed to converge"
-
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.