☰
Ubuntu 16.04源码编译PCL 1.8:依赖管理与避坑实战
2026/10/18 7:46:49 网站建设 项目流程

1. 为什么PCL 1.8在Ubuntu 16.04上是个“硬骨头”

搞点云处理的人,绕不开PCL(Point Cloud Library)。不管是做SLAM、三维重建,还是激光雷达标定,PCL基本都是标配。但如果你手上的开发环境恰好是Ubuntu 16.04,又想装PCL 1.8,那这件事就有点意思了——它不是那种“一条命令搞定”的活儿,而是一个需要你理解依赖关系、编译原理和版本兼容性的系统工程。

我先说结论:Ubuntu 16.04自带的PCL版本是1.7.x,而PCL 1.8引入了一些API变化和新模块(比如对VTK 7的支持、更完善的KDTree实现、以及一些点云滤波器的优化),很多人因为项目需要必须上1.8。但Ubuntu 16.04的默认软件源里没有PCL 1.8的预编译包,你只能自己编译,或者找第三方PPA。自己编译这件事,坑多到你怀疑人生。

这篇文章适合谁看?如果你是一个在Ubuntu 16.04上做点云相关开发的工程师或研究生,正在被PCL 1.8的安装折磨,或者你还没开始装但想提前知道会遇到什么,那这篇内容就是给你写的。我会把整个安装过程中最常遇到的问题、背后的原因、以及我实际踩过的坑,一个一个拆开讲清楚。不是那种“复制粘贴命令就完事”的教程,而是让你理解为什么要这么做,以及出问题了怎么自己排查。

2. 安装前的整体思路与方案选型

2.1 为什么我不推荐直接apt install

很多人的第一反应是sudo apt-get install libpcl-dev。在Ubuntu 16.04上,这条命令装出来的是PCL 1.7.1。如果你项目里用的API恰好是1.8才有的,比如某些pcl::PointCloud的新的成员函数,或者你依赖的某个库明确要求PCL 1.8,那1.7.1就不够用。

有人会想去找PPA。确实有一些第三方维护的PPA提供PCL 1.8的deb包,但这里有几个问题:第一,PPA的维护者不一定及时更新,依赖关系可能和你的系统其他库冲突;第二,PPA装的PCL可能缺少某些可选模块(比如可视化模块对VTK的依赖版本不对);第三,也是最关键的,你无法控制编译选项,比如是否开启CUDA、是否用特定的SIMD指令集优化。对于做性能敏感的点云处理来说,这些编译选项直接影响运行效率。

所以我的建议是:源码编译。虽然麻烦,但可控。

2.2 源码编译的整体流程

源码编译PCL 1.8的流程大致是这样的:先装一堆依赖库,然后从GitHub下载PCL 1.8的源码,用CMake配置,make编译,最后make install。听起来简单,但每一步都有坑。

依赖库这块,PCL 1.8需要的核心依赖包括:Boost(1.58以上)、Eigen(3.0以上)、FLANN(1.7以上)、VTK(6.2以上,但推荐7.x)、QHull(2012.1以上)。可选依赖包括:OpenNI2(点云采集)、Qt5(可视化界面)、CUDA(GPU加速)。Ubuntu 16.04的默认源里,Boost是1.58,Eigen是3.2,FLANN是1.7.1,VTK是6.2。看起来版本都够,但问题出在VTK上——PCL 1.8的可视化模块对VTK 7的支持更好,而Ubuntu 16.04默认是VTK 6.2,这就导致如果你要用可视化功能,可能需要自己编译VTK 7。

还有一个隐藏的坑:Ubuntu 16.04默认的GCC版本是5.4,这个版本编译PCL 1.8是没问题的,但如果你之前装过其他版本的GCC并且切换过默认编译器,可能会遇到C++标准不兼容的问题。PCL 1.8要求C++11,GCC 5.4默认支持C++11,但如果你用的是GCC 4.8,那就得手动加-std=c++11。

2.3 依赖库的版本匹配逻辑

这里我要展开讲一下为什么版本匹配这么重要。PCL的各个模块之间是有依赖关系的,比如pcl_visualization依赖VTK,pcl_kdtree依赖FLANN,pcl_search依赖FLANN和KdTree。如果你装的VTK版本和PCL编译时期望的不一致,链接阶段就会报错,典型的是“undefined reference tovtkXXX”这种。

我实测下来,PCL 1.8和VTK 7.1的搭配是最稳的。VTK 6.2虽然也能编译,但在使用pcl::visualization::PCLVisualizer的时候,某些渲染窗口的回调函数会有问题,比如鼠标事件不响应。这个坑我在一个三维重建项目里踩过,当时调了整整两天才发现是VTK版本的问题。

FLANN的版本也要注意。Ubuntu 16.04默认的FLANN 1.7.1是够用的,但如果你自己编译FLANN,记得要装libflann-dev,而且编译PCL的时候要确保CMake能找到FLANN的config文件。有时候FLANN装在了/usr/local/lib,但CMake默认只搜/usr/lib,这就需要手动指定FLANN_ROOT。

3. 核心依赖库的安装与避坑指南

3.1 Boost和Eigen:看似简单,也有暗坑

Boost和Eigen是PCL的基础依赖,Ubuntu 16.04的默认源里都有。安装命令很简单:

sudo apt-get install libboost-all-dev libeigen3-dev

但这里有个细节:libboost-all-dev会装一大堆Boost的组件,包括一些你可能用不到的。如果你磁盘空间紧张,可以只装必要的:libboost-system-dev libboost-filesystem-dev libboost-thread-dev libboost-date-time-dev libboost-iostreams-dev。不过我个人建议全装,因为PCL的某些模块可能会间接依赖其他Boost组件,少装了后面报错更麻烦。

Eigen的坑在于头文件路径。Ubuntu 16.04的libeigen3-dev装完后,头文件在/usr/include/eigen3,但有些代码里写的是#include <Eigen/Core>,这就需要你在编译时加-I/usr/include/eigen3。CMake里可以用include_directories(/usr/include/eigen3),或者更规范的做法是用find_package(Eigen3 REQUIRED)然后include_directories(${EIGEN3_INCLUDE_DIR})。

注意:如果你之前手动编译过Eigen并且装在了/usr/local/include/eigen3,那系统里可能有两个版本的Eigen。这时候CMake可能会找到错误的版本,导致编译报错。解决办法是用sudo updatedb && locate Eigen/Core确认实际路径,然后在CMake里显式指定。

3.2 FLANN:版本和路径的双重考验

FLANN的安装命令:

sudo apt-get install libflann-dev

Ubuntu 16.04装的是FLANN 1.7.1,这个版本对PCL 1.8来说够用。但如果你要自己编译FLANN(比如你需要最新的FLANN 1.8+),那就要注意了:自己编译的FLANN默认装在/usr/local,而PCL的CMake脚本默认去/usr找。这时候你需要在CMake配置PCL时加上:

cmake -DFLANN_INCLUDE_DIR=/usr/local/include \ -DFLANN_LIBRARY=/usr/local/lib/libflann.so ..

或者更简单的方法:在/usr/local/lib下确认有libflann.so和libflann_cpp.so,然后设置环境变量LD_LIBRARY_PATH包含/usr/local/lib。

我遇到过一个很隐蔽的问题:系统里同时存在libflann1.7和libflann1.8,编译PCL时CMake找到了1.8的头文件但链接到了1.7的库,结果运行时报“symbol lookup error”。排查方法是ldd你的可执行文件,看它实际链接的是哪个FLANN库。

3.3 VTK:最折腾的依赖,没有之一

VTK是PCL可视化模块的核心依赖,也是整个安装过程中最容易出问题的部分。Ubuntu 16.04默认的VTK是6.2,但PCL 1.8的官方文档推荐VTK 7.x。如果你不需要可视化功能,可以在编译PCL时加-DBUILD_visualization=OFF,这样就绕过了VTK。但如果你要做点云可视化,那VTK这一关必须过。

自己编译VTK 7.1的步骤大致是:下载源码,用CMake配置,make,make install。配置的时候要注意几个选项:

cmake -DCMAKE_INSTALL_PREFIX=/usr/local \ -DBUILD_SHARED_LIBS=ON \ -DVTK_Group_Qt=ON \ -DVTK_QT_VERSION=5 \ -DCMAKE_BUILD_TYPE=Release ..

VTK_Group_Qt和VTK_QT_VERSION这两个选项是为了支持Qt5的可视化界面。如果你不需要Qt,可以关掉。BUILD_SHARED_LIBS=ON是生成动态库,这样PCL链接的时候更方便。

编译VTK 7.1的时间比较长,取决于你的机器配置,大概20到40分钟。编译完之后,make install会把库装到/usr/local/lib,头文件在/usr/local/include/vtk-7.1。

提示:VTK 7.1编译完后,你可能需要运行sudo ldconfig来更新动态库缓存,否则PCL编译时可能找不到VTK的库。

还有一个坑:如果你之前装过VTK 6.2(比如通过apt),那系统里会有两个VTK。PCL的CMake脚本可能会优先找到6.2的config文件。解决办法是在CMake配置PCL时显式指定-DVTK_DIR=/usr/local/lib/cmake/vtk-7.1。

3.4 QHull和其他可选依赖

QHull是PCL做凸包计算和曲面重建时需要的库:

sudo apt-get install libqhull-dev

Ubuntu 16.04的QHull版本是2012.1,满足PCL 1.8的要求。但如果你要用pcl::ConcaveHull,建议装QHull 2015+,因为2012.1在某些边界情况下会有数值精度问题。自己编译QHull的话,注意它的头文件路径是/usr/local/include/libqhull,CMake里要设置QHULL_INCLUDE_DIR。

OpenNI2是可选的,只有你需要从深度相机(比如Kinect)采集点云时才需要。Ubuntu 16.04可以sudo apt-get install libopenni2-dev,但版本比较老。如果你用的是较新的深度相机,可能需要自己编译OpenNI2。

4. 源码编译PCL 1.8的完整实操过程

4.1 下载源码与目录结构

PCL 1.8的源码可以从GitHub的release页面下载。我建议下载tar.gz包而不是直接git clone,因为git clone会拉取整个历史记录,体积大且没必要。下载后解压:

tar -xzvf pcl-1.8.0.tar.gz cd pcl-1.8.0

目录结构大概是:common、io、kdtree、search、visualization等模块各占一个子目录,根目录有CMakeLists.txt。编译前建议先看一下CMakeLists.txt里的PCL_VERSION,确认是1.8.0。

4.2 CMake配置的关键参数

在源码目录下建一个build目录,然后进去运行CMake:

mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/local \ -DBUILD_visualization=ON \ -DBUILD_apps=OFF \ -DBUILD_examples=OFF \ -DBUILD_tools=OFF \ -DBUILD_global_tests=OFF \ -DVTK_DIR=/usr/local/lib/cmake/vtk-7.1 \ ..

这里解释一下几个关键参数:

  • CMAKE_BUILD_TYPE=Release:生成优化后的代码,运行速度快。如果你要调试PCL本身,可以用Debug,但编译出来的库会大很多。
  • CMAKE_INSTALL_PREFIX=/usr/local:安装路径。不建议装到/usr,因为会和apt装的PCL 1.7冲突。
  • BUILD_visualization=ON:开启可视化模块。如果你不需要,设为OFF可以省去VTK的麻烦。
  • BUILD_apps、BUILD_examples、BUILD_tools:这些是PCL自带的示例程序和工具,编译它们会额外花时间,而且容易因为依赖不全而报错。建议全部设为OFF。
  • BUILD_global_tests=OFF:不编译测试代码,省时间。
  • VTK_DIR:显式指定VTK的cmake配置目录,避免找到错误的VTK版本。

CMake配置完成后,它会输出一个摘要,列出哪些模块会被编译,哪些依赖找到了,哪些没找到。一定要仔细看这个摘要。如果某个你需要的模块显示“NO”,那就说明对应的依赖没找到,需要回去检查。

4.3 编译过程中的资源管理与时间预估

配置成功后,开始编译:

make -j$(nproc)

-j$(nproc)表示用所有CPU核心并行编译。PCL 1.8的代码量不小,在4核机器上大概需要30到50分钟,8核机器上20到30分钟。编译过程中内存占用会比较高,特别是visualization模块,因为VTK的模板代码很吃内存。如果你的机器内存小于8GB,建议用make -j2或者make -j4,避免内存耗尽导致编译进程被系统杀掉。

编译过程中最常见的错误是“fatal error: XXX.h: No such file or directory”。这通常是某个依赖的头文件路径没被正确包含。比如pcl_visualization编译时报“vtkRenderer.h not found”,那就是VTK的头文件路径没加进去。解决办法是检查CMake配置时VTK_DIR是否设置正确,或者手动在CMakeLists.txt里加include_directories(${VTK_INCLUDE_DIRS})。

另一个常见错误是链接错误:“undefined reference toXXX”。这通常是库的顺序问题或者库没找到。PCL的CMake脚本一般会处理好链接顺序,但如果你自己改了CMakeLists.txt,可能会打乱顺序。解决办法是确保依赖库在被依赖库的后面,比如-lpcl_visualization -lvtkRendering。

4.4 安装与环境变量配置

编译完成后,安装:

sudo make install

安装完成后,PCL的头文件在/usr/local/include/pcl-1.8,库文件在/usr/local/lib,CMake配置文件在/usr/local/share/pcl-1.8。

接下来要配置环境变量,让系统能找到PCL。编辑~/.bashrc,添加:

export PCL_ROOT=/usr/local export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

然后source ~/.bashrc。LD_LIBRARY_PATH是为了让运行时能找到PCL的动态库。如果你不设置这个,运行程序时可能会报“error while loading shared libraries: libpcl_common.so.1.8”。

注意:有些系统里/usr/local/lib已经在默认的库搜索路径里了,那就不需要额外设置LD_LIBRARY_PATH。你可以用ldconfig -p | grep pcl来确认。

4.5 验证安装是否成功

写一个最简单的测试程序:

#include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <iostream> int main() { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); cloud->width = 5; cloud->height = 1; cloud->points.resize(cloud->width * cloud->height); for (size_t i = 0; i < cloud->points.size(); ++i) { cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f); } std::cout << "Cloud size: " << cloud->points.size() << std::endl; return 0; }

编译命令:

g++ test_pcl.cpp -o test_pcl -I/usr/local/include/pcl-1.8 -I/usr/include/eigen3 -L/usr/local/lib -lpcl_common -lpcl_io

如果编译成功并且运行输出“Cloud size: 5”,那说明PCL 1.8的基本功能已经可用了。如果报错,根据错误信息回去检查对应的依赖。

5. 常见问题与排查技巧实录

5.1 编译时报“Could NOT find VTK”

这是最常见的问题。原因通常是CMake没找到VTK的配置文件。VTK的CMake配置文件叫VTKConfig.cmake,一般在/usr/local/lib/cmake/vtk-7.1或者/usr/lib/cmake/vtk-6.2。解决办法是在CMake配置PCL时加-DVTK_DIR=/path/to/vtk。如果你不确定VTK装在哪,用find / -name "VTKConfig.cmake" 2>/dev/null找一下。

还有一种情况是VTK找到了但版本不对。PCL 1.8要求VTK 6.2以上,如果你系统里只有VTK 5.x,那就会报版本不满足。这时候只能自己编译VTK 7.x。

5.2 运行时报“symbol lookup error”

这个错误通常发生在运行阶段,提示某个符号找不到。原因一般是链接时用的库版本和运行时加载的库版本不一致。比如编译时链接的是/usr/local/lib/libpcl_common.so.1.8,但运行时系统先找到了/usr/lib/libpcl_common.so.1.7。

排查方法:用ldd your_program | grep pcl看实际加载的是哪个库。如果是1.7的,那就需要调整LD_LIBRARY_PATH,把/usr/local/lib放在前面。或者更彻底的方法:卸载apt装的PCL 1.7(sudo apt-get remove libpcl-dev),避免冲突。

5.3 可视化模块编译失败

pcl_visualization模块编译失败的原因很多,最常见的是VTK版本不匹配和Qt版本问题。如果你用的是VTK 7.1和Qt5,一般没问题。但如果VTK编译时没开VTK_Group_Qt,那PCL的可视化模块就找不到Qt的接口,编译会报错。

解决办法:重新编译VTK,确保VTK_Group_Qt=ON和VTK_QT_VERSION=5。如果你不需要Qt界面,可以在PCL的CMake配置里加-DBUILD_visualization=OFF,直接跳过这个模块。

5.4 内存不足导致编译中断

编译PCL的visualization模块时,如果机器内存不够,make进程会被系统杀掉,报“Killed”或者“virtual memory exhausted”。解决办法是减少并行编译的job数,用make -j2或者make -j1。另外可以临时增加swap空间:

sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

编译完后再关掉swap:sudo swapoff /swapfile && sudo rm /swapfile。

5.5 常见问题速查表

问题现象可能原因解决办法
CMake报“Could NOT find VTK”VTK未安装或路径不对指定-DVTK_DIR或安装VTK 7.x
编译报“undefined reference”库链接顺序或版本不对检查ldd输出,调整LD_LIBRARY_PATH
运行报“symbol lookup error”运行时加载了旧版本库卸载旧版PCL或调整库搜索路径
可视化模块编译失败VTK未开Qt支持重编译VTK加VTK_Group_Qt=ON
编译过程被Killed内存不足减少-j数或增加swap
找不到Eigen头文件头文件路径未包含加-I/usr/include/eigen3
FLANN链接错误FLANN库路径不对指定FLANN_LIBRARY或ldconfig

5.6 几个我踩过的坑

第一个坑:我在一台机器上同时装了apt的PCL 1.7和源码编译的PCL 1.8,结果CMake配置新项目时总是找到1.7的config文件。后来发现是/usr/lib/cmake/pcl-1.7在CMake的搜索路径里优先级更高。解决办法是在项目的CMakeLists.txt里显式设置set(PCL_DIR "/usr/local/share/pcl-1.8")。

第二个坑:编译PCL 1.8时开了BUILD_examples=ON,结果examples里的某些代码依赖OpenNI2,而我没装OpenNI2,导致编译中断。后来把BUILD_examples关掉就顺利通过了。所以如果你不是非要看示例代码,建议关掉。

第三个坑:VTK 7.1编译完后没有运行sudo ldconfig,导致PCL编译时链接不到VTK的库。报错信息是“cannot find -lvtkCommonCore-7.1”,看起来像是库不存在,实际上是动态库缓存没更新。运行sudo ldconfig后问题解决。

6. 编译后的项目集成与CMake配置

6.1 在自己的项目中使用PCL 1.8

装好PCL 1.8后,你自己的项目怎么用它?最规范的方式是通过CMake的find_package:

cmake_minimum_required(VERSION 3.5) project(MyPCLProject) find_package(PCL 1.8 REQUIRED) include_directories(${PCL_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS}) add_executable(my_app main.cpp) target_link_libraries(my_app ${PCL_LIBRARIES})

这里的关键是find_package(PCL 1.8 REQUIRED),它会去找PCL 1.8的config文件。如果系统里同时有1.7和1.8,CMake可能会找到1.7。为了确保找到1.8,可以在find_package之前加:

set(PCL_DIR "/usr/local/share/pcl-1.8")

这样CMake就会直接去指定目录找。

6.2 处理多版本共存的问题

如果你的系统里既有apt装的PCL 1.7,又有源码编译的PCL 1.8,那在编译项目时一定要小心。除了设置PCL_DIR,还要确保链接时用的是1.8的库。可以在CMakeLists.txt里打印${PCL_LIBRARIES}看看实际链接的是哪些库:

message(STATUS "PCL libraries: ${PCL_LIBRARIES}") message(STATUS "PCL include dirs: ${PCL_INCLUDE_DIRS}")

如果输出的路径是/usr/lib而不是/usr/local/lib,那就说明找到的是1.7。这时候需要调整CMAKE_PREFIX_PATH:

set(CMAKE_PREFIX_PATH "/usr/local")

6.3 静态链接与动态链接的选择

默认情况下,PCL编译的是动态库。如果你想把PCL静态链接到你的程序里(比如为了发布独立的可执行文件),需要在编译PCL时加-DBUILD_SHARED_LIBS=OFF。但静态链接PCL会带来一些问题:第一,可执行文件体积会很大(可能几百MB);第二,某些模块(比如可视化)静态链接时会有符号冲突。所以除非有特殊需求,一般还是用动态链接。

7. 一些实用的经验补充

如果你只是想做点云的基本处理(滤波、分割、配准),不需要可视化,那完全可以跳过VTK,编译PCL时加-DBUILD_visualization=OFF。这样能省去大量麻烦,编译时间也能缩短一半。

另外,如果你用的是Docker做开发环境,可以考虑基于ubuntu:16.04镜像自己构建一个包含PCL 1.8的镜像。Dockerfile里把依赖安装和PCL编译的步骤写进去,一次构建,到处使用。这样避免了在每台机器上重复踩坑。构建的时候注意把apt-get的缓存清理掉,减小镜像体积。

还有一点:PCL 1.8的某些模块对C++标准有要求,比如pcl::PointCloud的某些新特性需要C++11。如果你在项目里用的是C++98,可能会编译失败。解决办法是在CMakeLists.txt里加set(CMAKE_CXX_STANDARD 11)和set(CMAKE_CXX_STANDARD_REQUIRED ON)。

最后分享一个我个人的习惯:每次装完这种复杂的库,我都会写一个简单的测试程序,把常用的模块(common、io、kdtree、search、visualization)都调用一遍,确认没有链接错误和运行时错误。这个测试程序我会保留下来,以后换机器或者重装系统时直接拿来验证环境是否配好。这个习惯帮我省了很多“以为装好了结果项目编译不过”的时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询