PCL+ VTK+QT ubuntu16.04配置 实现可视化点云
**
前言
因为项目需要,需要实现QT中实现点云显示,刚开始接触QT,有很多坑要躺,在坑了呆了4天,终于配置好了PCL1.8 + VTK6.3 + QT5.5 + ubuntu16.04!
网上参考的资料挺多,但都差不多,大部分都是基于windows下的开发,linux系统下的资料较少,刚从坑里出来,想记录下来,以免以后再用。
最初参考两篇博文
https://blog.csdn.net/wokaowokaowokao12345/article/details/51314439
https://blog.csdn.net/zyj8691/article/details/79162101
这两篇都是基于windows环境下的。
**
过程
感觉在坑里特别惨,是因为我之前在电脑里装了ROS,ROS是依赖VTK6.2 、 pcl1.7 、 qt5.5,在装qtcreator-ros-plugin时系统又装上了qt5.9,再加上系统原装的qt4,系统里有3个版本的qt,再加上一开始接触QT,对这些库的依赖并没有什么概念。
其实最核心的还是,VTK和PCL和QtCreator都要基于同一个qt。
安装的顺序时QT-VTK->PCL 因为 VTK依赖QT ,PCL依赖VTK和QT。
QT安装
QT的话应该安装qt5.5版本的,因为qt5.6版本以后,qt将QWebKit模块改成了QWebEngine,在VTK库和PCL库编译的时候都要用到这个模块。所以选择qt5.5安装并配置环境变量。
QT安装步骤和环境变量的配置就不赘述了,网上有很多。
想要在qt中实现可视化点云,就需要QVTKWigdet控件,这个控件是由vtk库编译而来的。网上还有一种方法是直接用代码的形式来解决的,起初尝试过,但失败了就没有再试。接下来就说VTK库的安装。
VTK库的安装
VTK采用源码安装,我用的是vtk6.3,VTK7.1应该也可以(没尝试过,但网上有很多ok的),VTK8.2尝试过(但好像VTK8.2太新了,PCL库报错,也有可能当时用的pcl并不是基于vtk8.2的)。
下载源码后,cd到VTK-6.3.0文件夹后,建立build文件夹。接下来配置cmake,我使用cmake-gui ,
1.选VTK_Group_Qt选项
2.将CMAKE_BUILD_TYPE改为Release
3.VTK_QT_VERSION改为5
按一下Configure按钮后,上面有关QT的路径应该都是上面QT5.5的安装路径。
配置好后,make 编译,VTK编译速度还可以,等一会就可以了
编译好后,sudo make install将库安装。
此时vtk的头文件应该都在/usr/local/include/vtk-6.3
库文件都在/usr/local/lib中。
编译VTK的库最主要的原因还是需要libQVTKWidgetPlugin.so库文件,路径为/home/username/VTK-6.3.0/build/lib。讲这个文件复制到(qt安装路径)/Tools/QtCreator/bin/plugins/designer(需要用sudo cp 命令来复制)
此时打开QT的UI界面,便会出现QVTK的控件。
PCL库的安装
PCL库也需要源码安装,下载pcl库的源码。同样的方法,建build文件夹,同样用cmake-gui配置cmake,检查VTK_DIR是不是安装的vtk库的路径,qt的版本等。
配置好后编译,PCL库编译需要挺长时间的。
同样,PCL的头文件应该都在/usr/local/include/pcl-1.8
库文件都在/usr/local/lib中。
QT工程依赖配置
新建qt工程,在.pro文件中配置依赖
源码如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtWidgets/QMainWindow>
#include <vtkAutoInit.h>
#include <boost/shared_ptr.hpp>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
VTK_MODULE_INIT(vtkRenderingOpenGL); //这个必须要加,不然会报错
VTK_MODULE_INIT(vtkInteractionStyle);
typedef pcl::PointXYZ VPoint;
typedef pcl::PointCloud<VPoint> VPointCloud;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
//point cloud data
VPointCloud::Ptr cloud;
pcl::visualization::PCLVisualizer::Ptr viewer;
//init VTK widget
void initialvtkWidget();
private slots:
void onOpen();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <vtkRenderWindow.h>
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initialvtkWidget();
connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(onOpen()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initialvtkWidget()
{
cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);
viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
viewer->addPointCloud(cloud, "cloud");
ui->CloudViewer->SetRenderWindow(viewer->getRenderWindow());
viewer->setupInteractor(ui->CloudViewer->GetInteractor(),ui->CloudViewer->GetRenderWindow());
ui->CloudViewer->update();
}
void MainWindow::onOpen()
{
//open PCD file
QString fileName = QFileDialog::getOpenFileName();
if (!fileName.isEmpty())
{
std::string file_name = fileName.toStdString();
//sensor_msgs::PointCloud2 cloud2;
pcl::PCLPointCloud2 cloud2;
//pcl::PointCloud<Eigen::MatrixXf> cloud2;
Eigen::Vector4f origin;
Eigen::Quaternionf orientation;
int pcd_version;
int data_type;
unsigned int data_idx;
pcl::PCDReader rd;
rd.readHeader(file_name, cloud2, origin, orientation, pcd_version, data_type, data_idx);
if (data_type == 0)
{
pcl::io::loadPCDFile(fileName.toStdString(), *cloud);
}
else if (data_type == 2)
{
pcl::PCDReader reader;
reader.read<pcl::PointXYZ>(fileName.toStdString(), *cloud);
}
viewer->updatePointCloud(cloud, "cloud");
viewer->resetCamera();
ui->CloudViewer->update();
}
}
效果图
END
这只是一个简单的demo,程序都是按照网上来的,最重要的问题解决了,接下来可以愉快的往下写了。哈哈哈哈哈。
如果PCL库、VTK库和qtcreator不是基于同一个qt的话,编译应该是没问题,但就是运行不起来,会出现很多稀奇古怪的问题。
参考了很多博文,跟这个相关的基本都看过,也不一一列了。希望对大家有用!