For this project, the virtual Ubuntu environment was provided by the Udacity. Install the Point Cloud Library (PCL) and clone the project starter code SFND_Lidar_Obstacle_Detection to the Ubuntu environment.
$ sudo apt install libpcl-dev
$ git clone https://github.com/udacity/SFND_Lidar_Obstacle_Detection.git ./Lidar_Obstacle_Detection
The directory structure of the starter code looks like:
- src
- render
box.h
: struct definition for box objectsrender.h
,render.cpp
: classes and methods for rendering objects
- sensors
lidar.h
: functions using ray casting for creating PCD
environment.cpp
: main file for using PCL viewer and processing/visualizing PCDprocessPointClouds.h
,processPointClouds.cpp
: functions for filtering, segmenting, clustering, boxing, loading and saving PCD
- render
Try compiling the lidar simulator and run it. A window with a simulated highway environment should pop up.
$ cd Lidar_Obstacle_Detection
$ mkdir build && cd build
$ cmake ..
$ make
$ ./environment
- Create a
Lidar
pointer object on the heap, taking two parameters:std::vector<Car>
andsetGroundSlope
of 0. TheLidar::scan()
method does a ray casting and returns a point cloud pointer objectpcl::PointCloud<pcl::PointXYZ>::Ptr
. CallrenderRays()
to plot rays on the viewer. (7140d05)
- Increase the lidar resolution by tweaking the constructor of
Lidar
class:numLayers
,horizontalAngleInc
. SetminDistance
to 5 meter to remove points from the vehicle's rooftop. Setsderr
to 0.2 to add some noises to the PCD. (16d5d3c)
- Remove rendering for the highway scene and rays, but enable rendering for the point cloud using
renderPointCloud()
. (80be982)
-
In the
processPointCloud.cpp
, to implement theProcessPointClouds::SegmentPlane()
method, use apcl::SACSegmentation<PointT>
object to segment the planar component from the input point cloud. Next to implement theSeparateClouds()
helper method, use apcl::ExtractIndices<PointT>
object to extract the points not belong to the plane as the obstacles. (24ae844) -
In the
environment.cpp
, create aProcessPointClouds<pcl::PointXYZ>
object, callSegmentPlane()
to separate the plane and obstacle. Finally, render the plane and obstacle point clouds. (24ae844)
- In the
processPointCloud.cpp
, to implement theProcessPointClouds::Clustering()
method, create a Kd-tree representationpcl::search::KdTree<PointT>::Ptr
for the input point cloud, configure the parameters for the Euclidean clustering objectpcl::EuclideanClusterExtraction<PointT>
and extract the clusters in the point cloud. In theenvironment.cpp
, call the clustering function on the segmented obstacle point cloud, render clustered obstacle in different colors. (a5761ac)
- Once point cloud clusters are found, we can add bounding boxes around the clusters. The boxed spaces should be considered as an area/object that our car is not allowed to enter, otherwise it would result a collision. Call
ProcessPointClouds::BoundingBox()
method, which finds the max and min point values as the boundary values for theBox
data structure. Then render theBox
structure for each cluster. (e85af3f)
- Create a new point processor for the real PCD from a
cityBlock
, the code is similar to thesimpleHighway
function. The point type ispcl::PointXYZI
where theI
indicates the intensity. The real PCD files are located atsrc/sensors/data/pcd/data_1/
directory. (5a0f545)
-
To implement the
ProcessPointClouds::FilterCloud()
in theprocessPointClouds.cpp
,pcl::VoxelGrid<PointT>
class is applied for Voxel Grid filtering, andpcl::CropBox<PointT>
class is applied for ROI-based filtering. TheEigen::Vector4f
class has four parameters representingx
,y
,z
coordinates and the last one should be 1.0. We are interested in a good amount of distance in front or at back of the car and surroundings of the car. Point cloud data outside of the ROI should be removed, including the rooftop points. (61ccf99) -
In the
environment.cpp
, callProcessPointClouds::FilterCloud()
function in thecityBlock()
. Input a leaf size of 0.2m, so that the voxel size is large enough to help speed up the processing but not so large that object definition is preserved.
-
Once having a filtered PCD, we can deploy the same segmentation and clustering techniques implemented previously in the
cityBlock()
. (85cc8c6) -
Tweak the
Eigen::Vector4f minPoint/maxPoint
forProcessPointClouds::FilterCloud()
andint minSize/maxSize
forProcessPointClouds::Clustering()
. (85c7c1a)
- Create a vector
stream
to store paths to the PCD files chronologically. Create a newcityBlock()
function, which processes the input point cloud from the external. In themain()
function ofenvironment.cpp
, inside the viewer update loop, read PCD file, process it and update the viewer. (221ce08)
The previous exercises have created a processing pipeline for detecting the obstacles using PCL segmentation and clustering methods. In the final project, we have to implement the same obstacle detection pipeline but with the 3D RANSAC segmentation, KD-Tree, and Euclidean clustering algorithm we created in the quizzes.
-
Create a
ProcessPointClouds::SegmentPlaneRansac()
function in theprocessPointClouds.cpp
, which uses the 3D RANSAC segmentation for plane implemented in the quiz. And call this segmentation function in thecityBlock()
ofenvironment.cpp
. (ba99dbd) -
Create
ProcessPointClouds::ClusteringEuclidean
and its helper functionProcessPointClouds::clusterHelper
in theprocessPointClouds.cpp
, which reuses the Euclidean clustering with KD-Tree with some modification from the quiz. And call this clustering function in thecityBlock()
ofenvironment.cpp
. (0a5efcd) -
Before building the final project, make sure the macro
CUSTOM_METHOD
is defined in theenvironment.cpp
so that the custom implementations in the Step 1 and 2 are used. Otherwise, defining macroPCL_METHOD
will use the segmentation and clustering functions provided by PCL library.
pcl::PointXYZ
: https://pointclouds.org/documentation/structpcl_1_1_point_x_y_z.html
Example of segmenting the Plane with PCL: https://pointclouds.org/documentation/tutorials/extract_indices.html
Example of Euclidean Cluster Extraction: https://pointclouds.org/documentation/tutorials/cluster_extraction.html
Example of Voxel Grid filtering: https://pointclouds.org/documentation/tutorials/voxel_grid.html
Example of Crop Box filtering: https://pointclouds.org/documentation/classpcl_1_1_crop_box.html