Main Content

Extract On-Road and Off-Road Points from Point Cloud

This example shows how to extract on-road and off-road points from point cloud data.

Detecting road boundaries is an essential part of autonomous vehicle localization and decision-making. Road boundaries usually include curbs, walls, and berms.

In most scenarios, the boundary of a road is defined by the curb. A curb connects the roadway to the sidewalk. Curbs are important for safe driving, as they distinguish the drivable area from the restricted region.

To extract curb points, you must first process the point cloud data to distinguish on-road and off-road points. The on-road area consists of sidewalks, curbs, and road surfaces. The off-road area usually consists of trees, buildings, and other objects. You can extract on-road and off-road points using algorithms such as plane-fitting or ground segmentation, depending on your input data.

Plane-Fitting Method

Preprocess Point Cloud

Read the point cloud data into the workspace.

inputPtCloud = pcread(fullfile(toolboxdir("lidar"),"lidardata", ...
               "sampleWPIPointClouds","pointClouds","005.pcd"));

Extract a region of interest containing a road area from the point cloud.

xLim = [0 25]; 
yLim = [-10 10];
roiIdx = findPointsInROI(inputPtCloud,[xLim yLim inputPtCloud.ZLimits]);
ptCloud = select(inputPtCloud,roiIdx,OutputSize="full");

Divide the point cloud into grids.

gridSize = [1 1]; % in meters
ptCloud = pointCloud(reshape(ptCloud.Location(:,:,:),[],3));
numGridsX = round(diff(ptCloud.XLimits)/gridSize(1));
numGridsY = round(diff(ptCloud.YLimits)/gridSize(2));

Extract the point indices from each grid.

indices = pcbin(ptCloud,[numGridsX numGridsY 1]);

Extract Off-Road Points

Specify an off-road height threshold.

offRoadHeightThreshold = 1.5; % in meters

Extract the indices of the off-road points from the grids.

offRoadPointsIdx = false(size(ptCloud.Location,1),1);
for i=1:numGridsX*numGridsY
    if ~isempty(indices{i})
        gridHeight = ptCloud.Location(indices{i},3);
        if (max(gridHeight) - min(gridHeight)) > offRoadHeightThreshold
            offRoadPointsIdx(indices{i}) = true;
        end
    end
end

Extract the off-road point cloud.

offRoadPtCloud = select(inputPtCloud,offRoadPointsIdx);

Extract On-Road Points

Extract the on-road points from the remaining points in the point cloud by using the pcfitplane function. Alternatively, you can use the segmentGroundFromLidarData function.

remainingPtCloud = select(inputPtCloud,~offRoadPointsIdx,OutputSize="full");
[~,inlierIdx,~] = pcfitplane(remainingPtCloud,1,[0 0 1]);
onRoadPtCloud = select(remainingPtCloud,inlierIdx,OutputSize="full");

Display the on-road and off-road points.

pcshowpair(offRoadPtCloud,onRoadPtCloud)

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

Ground Segmentation Method

Preprocess Point Cloud

Read point cloud data into the workspace.

ptCloud = pcread("HDL64LidarData.pcd");

Organize the point cloud.

ptCloud = pcorganize(ptCloud,lidarParameters("HDL64E",1024));

Extract a region of interest containing a road area from the point cloud.

roi = [-25 25 -10 24 ptCloud.ZLimits];
indices = findPointsInROI(ptCloud,roi);
ptCloud = select(ptCloud,indices,OutputSize="full");

Extract On-Road and Off-Road Points

Segment the on-road and off-road points from the point cloud by using the segmentGroundSMRF function. Alternatively, you can use the segmentGroundFromLidarData function.

[~,offRoadPtCloud,onRoadPtCloud] = segmentGroundSMRF(ptCloud);

Display the on-road and off-road points.

pcshowpair(offRoadPtCloud,onRoadPtCloud)

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

Detecting Road Boundary

After extracting the on-road and off-road points, you can further process them by using the detectRoadAngles function, to identify the road directions. Then, use the segmentCurbPoints function to extract the curb points from the on-road point cloud.

See Also

Functions

Related Topics