PCL包括多个子模块库。最重要的PCL模块库有如下:过滤器Filters、特征Features、关键点Keypoints、配准Registration、Kd树Kd-tree、八叉树Octree、切分Segmentation、Sample Consensus、Surface、Range Image、文件读写I/O、Visualization、通用库Common、Search
PCL中的所有模块和算法都是通过Boost共享指针来传送数据的,因而避免了多次复制系统中已存在的数据的需要
ROS中已经安装了pcl,不必再安装了,而且网上给的那个源一直添加失败,服务器在国外。但是ROS的pcl缺工具包,比如查看点云图片的pcl_viewer
。它的安装命令是:sudo apt-get install pcl-tools
优点:
可以表达物体的空间轮廓和具体位置
点云本身和视角无关,也就是你可以任意旋转,可以从不同角度和方向观察一个点云,而且不同的点云只要在同一个坐标系下就可以直接融合
缺点:
点云并不是稠密的表达,一般比较稀疏,放大了看,会看到一个个孤立的点。它的周围是黑的,也就是没有信息。所以在空间很多位置其实没有点云,这部分的信息是缺失的。
点云的分辨率和离相机的距离有关。离近了看不清是个什么东西,只能拉的很远才能看个大概。
安装
编译pcl-1.81
2
3
4
5
6mkdir build
cd build
# 配置cmake
cmake -DCMAKE_BUILD_TYPE=None -DCMAKE_INSTALL_PREFIX=/usr \ -DBUILD_GPU=ON-DBUILD_apps=ON -DBUILD_examples=ON \ -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make install
如果ubuntu 22.04且通过sudo apt install libpcl-dev
安装的pcl。那么pcl版本可能是1.12,如果vtk版本正好又是9.1,二者存在冲突会导致不能正常显示。
cmake配置
1 | cmake_minimum_required(VERSION 2.6) |
PCL中常见的PointT类型
PointXYZ
是使用最常见的一个点数据类型,因为他之包含三维XYZ坐标信息,这三个浮点数附加一个浮点数来满足存储对齐,可以通过points[i].data[0]
或者points[i].x
访问点X的坐标值1
2
3
4
5
6
7
8
9
10union
{
float data[4];
struct
{
float x;
float y;
float z;
};
};
PointXYZRGB
也是个union,成员如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15union{
float data[4];
struct
{
float x;
float y;
float z;
};
};
union{
struct{
float rgb;
};
float data_c[4];
};
在使用PCL库的时候,经常需要显示点云,可以用下面这段代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
PointCloudT::Ptr cloud(new PointCloudT);
cloud->is_dense = false;
// 打开点云文件,获取的是vertex
if(pcl::io::loadPLYFile("file.ply", *cloud) <0 )
{
PCL_ERROR("loading cloud failed !");
return -1;
}
cout<< "点云共有: "<< cloud->size()<<"个点"<<endl; //文件中vertex的个数
pcl::visualization::CloudViewer viewer ("Viewer");
viewer.showCloud(cloud);
while (!viewer.wasStopped ())
{
}
变换点云
1 | pcl::transformPointCloud (*cloud_in, *cloud_out, matrix); |
cloud_in
为源点云,cloud_out
为变换后的点云,注意这里的matrix是4X4的欧拉矩阵,也就是第一行为R,t;第二行为0,1的矩阵
PCLVisualizer类与CloudViewer类
对于CloudViewer类来说,其方法有大致以下几类1
2
3
4
5
6
7
8
9
10
11
12void showCloud()
void wasStopped() // 关闭窗口
void runOnVisualizationThread()
void runOnVisualizationThreadOnce ()
void removeVisualizationCallable()
// 键盘鼠标的响应
boost::signals2::connection registerKeyboardCallback()
boost::signals2::connection registerMouseCallback()
boost::signals2::connection registerPointPickingCallback()
常用代码:1
2
3
4
5
6pcl::visualization::CloudViewer viewer("3D Point Cloud Viewer");
// 除了显示什么都不能干
viewer.showCloud(m_cloud);
while(!viewer.wasStopped())
{
}
如果只是简单显示点云,调用CloudViewer就可以了。PCLVisualizer
更加强大,可以改变窗口背景,还可以添加球体,设置文本,功能特别丰富1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0);
int v1(0);
int v1(1);
// 视窗的x轴最小值,y轴最小值,x轴最大值,y轴最大值
viewer->createViewPort(0.0, 0, 0.5, 1.0, v1); //创建左视窗
viewer->createViewPort(0.5, 0, 1.0, 1.0, v2); //创建右视窗
viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");
viewer->addCoordinateSystem(1.0);
viewer->initCameraParameters();
// 代码最后,都会出现这样一个while循环,在spinOnce中为界面刷新保留了时间
while (!viewer->wasStopped())
{
viewer->spinOnce(100); // 多长时间调用内部渲染一次
boost::this_thread::sleep(boost::posix_time::microseconds(100000)); //延时0.1秒
}
addPointCloud
函数将点云添加到视窗对象中,并定义一个唯一的字符串作为ID号,利用此字符串保证在其他成员方法中也能标识引用该点云,多次调用addPointCloud(),可以实现多个点云的添加,每调用一次就创建一个新的ID号。如果想更新一个已经显示的点云,可以使用updatePointCloud
函数。删除有removePointCloud(ID号)
和removeAllPointClouds
。 这里使用的是最简单的一个重载,此外可以在第二个参数添加PointCloudColorHandler
或PointCloudColorHandler
PCLVisualizer类的键盘事件
1 | bool next_iteration = false; |
其他常用函数
1 | // 初始化相机参数 |
还可以对不同的视窗添加文字和背景颜色