Con l'arrivo del sensore lidar sugli IPhone (rip Project Tango) forse e' il caso di ritirare fuori le librerie per trattare le nuvole di punti come PCL
Per installare la liberia su Debian e' sufficiente
apt-get install libpcl-dev
che si porta dietro un po' di dipendenze come boost
I primi passi sono ovviamente quelli di inserire la libreria in un progetto. Per questo sono partito da QTCreator con le varie opzioni di Make
Compilazione con CMake
per la compilazione si devono aggiungere le righe in giallo al file CMakeLists.txt. Attenzione che in PCL le funzioni sono distribuite in vari moduli che devono essere specificati in REQUIRED COMPONENTS
cmake_minimum_required(VERSION 3.5)
project(nuvola LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(PCL 1.3 REQUIRED COMPONENTS common io features)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(nuvola main.cpp)
target_link_libraries(nuvola ${PCL_LIBRARIES})
Compilazione con QMake
TEMPLATE = app
CONFIG += console c++14
CONFIG -= app_bundle
CONFIG -= qt
CONFIG += link_pkgconfig
PKGCONFIG += eigen3
INCLUDEPATH += /usr/include/pcl-1.11
LIBS += -L/usr/lib/x86_64-linux-gnu -lpcl_common -lpcl_io -lpcl_features -lpcl_search
QT += widgets
SOURCES += \
main.cpp
Compilazione con Make
Per verificare quali sono gli switch di compilazione necessari per usare make si puo'usare
pkg-config --cflags --libs pcl_commons-1.7
anche in questo caso si deve ripetere l'operazione per ogni modulo utilizzato
Di seguito un semplice esempio di come leggere un file PCD, calcolare le normali e stampare i dati a schermo
===========================================
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
using namespace std;
int main()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ> ("/home/luca/gabriele.pcd", *cloud) == -1) //* load the file
{
PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
return (-1);
}
//std::cout << "Loaded " << cloud->width * cloud->height << " data points from test_pcd.pcd with the following fields: " << std::endl;
/*for (size_t i = 0; i < cloud->points.size (); ++i)
std::cout << " " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl;
*/
// 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);
//std::cout << endl << cloud_normals->size() << endl;
// cloud_normals->size () should have the same size as the input cloud->size ()*
int i = 0;
for (pcl::Normal n : *cloud_normals) {
//std::cerr << i << " n = " << n.normal_x << ", " << n.normal_y << ", " << n.normal_z << "\n";
std::cout << n.normal_x << "," << n.normal_y << "," << n.normal_z << "\n";
i++;
}
return 0;
}