项目目录

.
├── .vscode
│   ├── launch.json
│   └── setting.json
├── build
├── CMakeLists.txt
├── data
│   └── FeatureLocation8.pcd
├── include
├── NormalEstimation.cpp
└── src

4 directories, 3 files

CMake配置

VScode插件

在这里插入图片描述

CMakeLists.txt

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)

project(1_NORMAL_ESTIMATION)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # 显示代码警告
set(CMAKE_BUILD_TYPE Debug) # 设置Debug模式,否则无法在断点处停下

find_package(PCL 1.3 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

include_directories(${CMAKE_SOURCE_DIR}/include)

add_executable(NormalEstimation NormalEstimation.cpp)
target_link_libraries(NormalEstimation ${PCL_LIBRARIES})

launch.json

添加launch.json文件:
在这里插入图片描述
修改launch.json文件的内容后如下图所示:
在这里插入图片描述

task.json

添加task.json文件:
在这里插入图片描述
在这里插入图片描述
修改tasks.json的内容后如下图所示:
在这里插入图片描述

开始调试

设置一个断点:
在这里插入图片描述
开始调试(快捷键F5):
在这里插入图片描述
一系列调试按钮:
在这里插入图片描述

其他配置

为了能够方便地跳转到PCL库的头文件,可以设置一下c_cpp_properties.json
在这里插入图片描述

源码

launch.json

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++ - 生成和调试活动文件",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/NormalEstimation",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "Build",
            "miDebuggerPath": "/usr/bin/gdb"
        }
    ]
}

task.json

{   
    "version": "2.0.0",
    "options": {
        "cwd": "${workspaceFolder}/build"
    },
    "tasks": [
        {
            "type": "shell",
            "label": "cmake",
            "command": "cmake",
            "args": [
                ".."
            ]
        },
        {
            "label": "make",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "command": "make",
            "args": [

            ]
        },
        {
            "label": "Build",
            "dependsOrder": "sequence", // 按列出的顺序执行任务依赖项
            "dependsOn":[
                "cmake",
                "make"
            ]
        }
    ]
}

NormalEstimation.cpp

#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/io/pcd_io.h>

void test1(std::string incloudfile)
{
    // Load cloud
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile(incloudfile.c_str(), *cloud);

    // Create the normal estimation class, and pass the input dataset to it
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setInputCloud(cloud);

    // Create an empty kdtree representation, and pass it to the normal estimation object.
    // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    ne.setSearchMethod(tree);

    // Output datasets
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);

    // Use all neighbors in a sphere of radius 3cm
    ne.setRadiusSearch(0.03);

    // Compute the features
    ne.compute(*cloud_normals);

    // cloud_normals->size () should have the same size as the input cloud->size ()
}

void test2(std::string incloudfile)
{
    // Load cloud
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile(incloudfile.c_str(), *cloud);

    // Create a set of indices to be used. For simplicity, we're going to be using the first 10% of the points in cloud
    std::vector<int> indices(std::floor(cloud->size() / 10));
    for (std::size_t i = 0; i < indices.size(); ++i)
        indices[i] = i;

    // Create the normal estimation class, and pass the input dataset to it
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setInputCloud(cloud);

    // Pass the indices
    pcl::shared_ptr<std::vector<int>> indicesptr(new std::vector<int>(indices));
    ne.setIndices(indicesptr);

    // Create an empty kdtree representation, and pass it to the normal estimation object.
    // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    ne.setSearchMethod(tree);

    // Output datasets
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);

    // Use all neighbors in a sphere of radius 3cm
    ne.setRadiusSearch(0.03);

    // Compute the features
    ne.compute(*cloud_normals);

    // cloud_normals->size () should have the same size as the input indicesptr->size ()
}

void test3(std::string incloudfile)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_downsampled(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::io::loadPCDFile(incloudfile.c_str(), *cloud);
    pcl::io::loadPCDFile(incloudfile.c_str(), *cloud_downsampled);

    // Create the normal estimation class, and pass the input dataset to it
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setInputCloud(cloud_downsampled);

    // Pass the original data (before downsampling) as the search surface
    ne.setSearchSurface(cloud);

    // Create an empty kdtree representation, and pass it to the normal estimation object.
    // Its content will be filled inside the object, based on the given surface dataset.
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    ne.setSearchMethod(tree);

    // Output datasets
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);

    // Use all neighbors in a sphere of radius 3cm
    ne.setRadiusSearch(0.03);

    // Compute the features
    ne.compute(*cloud_normals);

    // cloud_normals->size () should have the same size as the input cloud_downsampled->size ()
}

int main(int argc, char *argv[])
{
    // std::string incloudfile = argv[1];
    // if(argv[2] != nullptr)
    //     std::string outcloudfile = argv[2];
    std::string incloudfile;
    incloudfile = "./data/FeatureLocation8.pcd";
    test1(incloudfile);
    std::cout << "End!" << std::endl;
    return 0;
}