Main Content

pcregisterndt

Register two point clouds using NDT algorithm

Description

tform = pcregisterndt(moving,fixed,gridStep) returns the rigid transformation that registers the moving point cloud with the fixed point cloud. The fixed point cloud is voxelized into cubes of size gridStep.

The registration algorithm is based on the normal-distributions transform (NDT) algorithm [1] [2]. Best performance of this iterative process requires adjusting properties for your data. To improve accuracy and efficiency of registration, consider downsampling the moving point cloud by using pcdownsample before using pcregisterndt.

example

[tform,movingReg] = pcregisterndt(___) also returns the transformed point cloud that aligns with the fixed point cloud.

[tform,movingReg,rmse] = pcregisterndt(___) also returns the root mean square error of the Euclidean distance between the aligned point clouds.

[___] = pcregisterndt(___,Name=Value) specifies options using one or more name-value arguments in addition to any combination of arguments from previous syntaxes. For example, MaxIterations=20 stops the NDT algorithm after 20 iterations.

Examples

collapse all

Load point cloud data.

ld = load('livingRoom.mat');
moving = ld.livingRoomData{1};
fixed = ld.livingRoomData{2};
figure
pcshowpair(moving,fixed,VerticalAxis='Y',VerticalAxisDir='Down')

Figure contains an axes object. The axes object contains 2 objects of type scatter.

To improve the efficiency and accuracy of the NDT registration algorithm, downsample the moving point cloud.

movingDownsampled = pcdownsample(moving,'gridAverage',0.1);

Voxelize the point cloud into cubes of sidelength 0.5. Apply the rigid registration using the NDT algorithm.

gridStep = 0.5;
tform = pcregisterndt(movingDownsampled,fixed,gridStep);

Visualize the alignment.

movingReg = pctransform(moving,tform);
figure
pcshowpair(movingReg,fixed,VerticalAxis='Y',VerticalAxisDir='Down')

Figure contains an axes object. The axes object contains 2 objects of type scatter.

Construct a velodyneFileReader object.

veloReader = velodyneFileReader('lidarData_ConstructionRoad.pcap','HDL32E');

Read and visualize two lidar point clouds.

frameNumber = 1;
skipFrame   = 5;
fixed = readFrame(veloReader,frameNumber);
moving = readFrame(veloReader,frameNumber + skipFrame);

Segment the ground plane and remove it from the fixed point cloud.

groundPtsIdxFixed = segmentGroundFromLidarData(fixed);
fixedSeg = select(fixed,~groundPtsIdxFixed,OutputSize='full');

Segment the ground plane and remove it from the moving point cloud.

groundPtsIdxMoving = segmentGroundFromLidarData(moving);
movingSeg = select(moving,~groundPtsIdxMoving,OutputSize='full');

Downsample the moving point cloud to improve accuracy and the efficiency of processing the points.

movingDownsampled = pcdownsample(movingSeg,gridAverage=0.2);

Register the moving point cloud with respect to the fixed point cloud.

gridStep = 5;
tform = pcregisterndt(movingDownsampled,fixedSeg,gridStep);

Transform the moving point cloud using an estimated rigid transformation.

movingReg = pctransform(moving,tform);

Visualize the alignment of the point clouds.

figure
pcshowpair(movingReg,fixed)

Figure contains an axes object. The axes object contains 2 objects of type scatter.

Input Arguments

collapse all

Moving point cloud, specified as a pointCloud object.

Fixed point cloud, specified as a pointCloud object.

Size of the 3-D cube that voxelizes the fixed point cloud, specified as a positive scalar.

Data Types: single | double

Name-Value Arguments

collapse all

Specify optional pairs of arguments as Name1=Value1,...,NameN=ValueN, where Name is the argument name and Value is the corresponding value. Name-value arguments must appear after other arguments, but the order of the pairs does not matter.

Example: MaxIterations=20 stops the NDT algorithm after 20 iterations.

Initial rigid transformation, specified as a rigidtform3d object. Set the initial transformation to a coarse estimate. If you do not provide a course or initial estimate, the function uses a rigidtform3d object that contains a translation that moves the center of the moving points to the center of the fixed points.

Expected percentage of outliers with respect to a normal distribution, specified as a scalar in the range [0, 1). The NDT algorithm assumes a point is generated by a mixture of a normal distribution for inliers and a uniform distribution for outliers. A larger value of OutlierRatio reduces the influence of outliers.

Data Types: single | double

Maximum number of iterations before NDT stops, specified as a positive integer.

Data Types: single | double

Tolerance between consecutive NDT iterations, specified as a 2-element vector with nonnegative values. The vector, [Tdiff Rdiff], represents the tolerance of absolute difference in translation and rotation estimated in consecutive NDT iterations. Tdiff measures the Euclidean distance between two translation vectors. Rdiff measures the angular difference in degrees. The algorithm stops when the difference between estimated rigid transformations in the most recent consecutive iterations falls below the specified tolerance value.

Data Types: single | double

Display progress information, specified as a numeric or logical 0 (false) or 1 (true). To display the progress information, set Verbose to true.

Output Arguments

collapse all

Rigid transformation, returned as a rigidtform3d object. tform describes the rigid 3-D transformation that registers the moving point cloud, moving, to the fixed point cloud, fixed.

Transformed point cloud, returned as a pointCloud object. The transformed point cloud is aligned with the fixed point cloud, fixed.

Root mean square error, returned as a positive numeric scalar that represents the Euclidean distance between the aligned points. The aligned points is a result of the moving point cloud transformed by the tform output and the fixed point cloud. For each point in the fixed point cloud, the algorithm finds the closest point in the transformed point cloud, movingReg, then computes the Euclidean distance between the points, and then computes the rmse. A low rmse value indicates a more accurate registration. The rmse calculation is:

rmse = sqrt(sum(distance.^2,'all')/numel(distance));

Data Types: single | double

Algorithms

collapse all

References

[1] Biber, P., and W. Straßer. “The Normal Distributions Transform: A New Approach to Laser Scan Matching.” Proceedings of IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS). Las Vegas, NV. Vol. 3, November 2003, pp. 2743–2748.

[2] Magnusson, M. “The Three-Dimensional Normal-Distributions Transform — an Efficient Representation for Registration, Surface Analysis, and Loop Detection.” Ph.D. Thesis. Örebro University, Örebro, Sweden, 2013.

Extended Capabilities

expand all

C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.

GPU Code Generation
Generate CUDA® code for NVIDIA® GPUs using GPU Coder™.

Version History

Introduced in R2018a

expand all