Ubuntu 18.04部署LSD-SLAM:直接法SLAM环境配置与编译指南

1. 项目概述:在Ubuntu 18.04上部署LSD-SLAM

如果你正在研究机器人视觉或者三维重建,大概率听说过ORB-SLAM、VINS-Mono这些大名鼎鼎的算法。但今天我想聊的是一个在SLAM(即时定位与地图构建)发展史上有着独特地位的开源项目——LSD-SLAM。它全称是Large-Scale Direct monocular SLAM,由德国慕尼黑工业大学计算机视觉组在2014年提出。与当时主流的基于特征点的方法不同,LSD-SLAM采用了直接法,直接利用图像像素的灰度信息进行位姿估计和稠密地图构建,这为单目相机实现大尺度、半稠密的环境重建提供了可能。

然而,这个经典项目在较新的系统上编译运行,常常会遇到各种依赖和兼容性问题。特别是对于很多实验室和开发者来说,Ubuntu 18.04 LTS(Bionic Beaver)依然是一个稳定且广泛使用的开发平台,许多机器人中间件(如ROS Melodic)也基于此版本。因此,在Ubuntu 18.04上成功搭建并运行LSD-SLAM,就成了一道必须跨过的门槛。这不仅仅是“跑通一个Demo”,更是理解直接法SLAM原理、掌握复杂开源项目环境配置、以及为后续算法研究和二次开发打下基础的关键一步。本文将基于我多次在Ubuntu 18.04上部署LSD-SLAM的经验,为你拆解整个过程,从环境准备、源码编译、到运行调试和问题排查,提供一份可直接“抄作业”的详细指南。

2. 环境准备与核心依赖解析

在Ubuntu 18.04上编译一个像LSD-SLAM这样有一定历史的C++项目,第一步也是最关键的一步,就是搭建一个正确且完整的依赖环境。很多编译失败的问题,根源都在于此。

2.1 系统基础环境确认

首先,确保你的Ubuntu 18.04系统是最新的。打开终端,执行以下命令更新软件源和已安装的包:

sudo apt update sudo apt upgrade -y

接下来,安装编译所需的通用工具链,包括构建工具、版本控制工具和必要的开发库:

sudo apt install -y build-essential cmake git pkg-config
  • build-essential:包含了GCC/G++编译器、make等核心编译工具。
  • cmake:LSD-SLAM使用CMake作为构建系统,这是必须的。
  • git:用于从GitHub克隆源码。
  • pkg-config:帮助查找库文件和头文件路径的工具。

2.2 核心依赖库的安装与版本选择

LSD-SLAM的核心依赖包括OpenCV、Eigen、SuiteSparse、Pangolin等。在Ubuntu 18.04的官方仓库中,这些库的版本可能不完全匹配LSD-SLAM原始代码的要求,需要特别注意。

1. OpenCV:LSD-SLAM对OpenCV的版本有一定要求,通常需要OpenCV 2.x或3.x。Ubuntu 18.04默认仓库提供的是OpenCV 3.2。这个版本基本兼容,但为了减少潜在问题,我建议安装一个更通用的OpenCV 3.4.x。我们可以通过源码编译安装,但为了快速部署,使用官方仓库版本也是可行的。

sudo apt install -y libopencv-dev

安装后,可以通过pkg-config --modversion opencv检查版本,确认是3.2.0。

2. Eigen3:Eigen是一个高性能的C++模板库,用于线性代数运算。LSD-SLAM大量使用了它。Ubuntu 18.04仓库中的Eigen3版本(通常是3.3.4)是合适的。

sudo apt install -y libeigen3-dev

3. SuiteSparse:SuiteSparse是一套用于稀疏矩阵计算的库,LSD-SLAM用它来求解大规模线性系统。这是必须的依赖。

sudo apt install -y libsuitesparse-dev

4. Pangolin:这是一个轻量级的OpenGL显示/交互库,LSD-SLAM用它来可视化相机轨迹和重建的地图。这是最容易出问题的依赖之一。Ubuntu仓库中的版本可能太旧或缺失。最可靠的方式是从源码编译安装。

# 安装Pangolin的依赖 sudo apt install -y libglew-dev libwayland-dev libxkbcommon-dev wayland-protocols sudo apt install -y ffmpeg libavcodec-dev libavutil-dev libavformat-dev libswscale-dev sudo apt install -y libpng-dev libjpeg-dev # 克隆并编译Pangolin cd ~ git clone https://github.com/stevenlovegrove/Pangolin.git cd Pangolin mkdir build && cd build cmake .. make -j$(nproc) sudo make install

注意:编译Pangolin时,如果遇到关于Wayland的错误,可以尝试在CMake时加上-DBUILD_WAYLAND=OFF来禁用Wayland支持,因为很多问题源于Wayland与X11的兼容性。命令改为:cmake -DBUILD_WAYLAND=OFF ..

5. 其他可选但推荐的库:

  • libboost-all-dev:Boost库,一些工具可能用到。
  • libtbb-dev:Intel线程构建块,用于并行计算,可能提升性能。

2.3 创建工作空间与获取源码

不建议在系统目录直接编译。创建一个独立的工作目录是个好习惯。

mkdir -p ~/lsd_slam_ws/src cd ~/lsd_slam_ws/src

接下来获取源码。原始的LSD-SLAM仓库(tum-vision/lsd_slam)可能对最新系统支持不佳。我们可以使用一个针对Ubuntu 18.04适配过的分支或复刻版本。根据网络信息,Rick0514/Ubuntu18.04-LSD-SLAM是一个可行的选择。

git clone https://github.com/Rick0514/Ubuntu18.04-LSD-SLAM.git lsd_slam cd lsd_slam

这个仓库通常已经包含了lsd_slam_core(核心算法库)、lsd_slam_viewer(可视化工具)等子模块或目录结构。

3. 源码编译与关键配置修改

环境就绪后,就进入了核心的编译环节。LSD-SLAM的CMakeLists.txt可能需要进行一些调整才能适应Ubuntu 18.04的环境。

3.1 编译lsd_slam_core核心库

首先编译最核心的部分。进入lsd_slam_core目录(如果仓库结构如此):

cd ~/lsd_slam_ws/src/lsd_slam/lsd_slam_core mkdir build cd build

现在运行CMake生成Makefile。这里有几个关键点:

  1. 指定Eigen3路径:虽然我们安装了libeigen3-dev,但有时CMake找不到。可以显式指定。
  2. 处理OpenCV版本:确保CMake找到的是我们安装的OpenCV 3.2。

一个相对稳健的CMake命令如下:

cmake .. -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/usr/include/eigen3
  • -DCMAKE_BUILD_TYPE=Release:指定为发布模式,编译器会进行优化,程序运行更快。
  • -DEIGEN3_INCLUDE_DIR:明确告诉CMake Eigen3头文件的位置。

执行后,仔细观察CMake的输出。重点关注以下几行:

  • Found OpenCV: ... (found version 3.2.0)确认OpenCV版本。
  • Found Eigen3: ...确认Eigen3找到。
  • Found Pangolin: ...确认Pangolin找到。

如果Pangolin找不到,可能需要设置Pangolin_DIR变量,指向Pangolin安装后的CMake配置文件路径,通常是/usr/local/lib/cmake/Pangolin

CMake成功后,开始编译:

make -j$(nproc)

-j$(nproc)表示使用你电脑所有可用的CPU核心并行编译,能显著加快速度。

3.2 编译lsd_slam_viewer可视化工具

核心库编译成功后,再编译可视化部分。回到源码根目录,进入lsd_slam_viewer

cd ~/lsd_slam_ws/src/lsd_slam/lsd_slam_viewer mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc)

可视化工具依赖于核心库和Pangolin。如果CMake报错找不到lsd_slam_core,可能需要检查上一步核心库是否成功编译,并生成了liblsd_slam_core.so之类的库文件。有时需要在CMake时通过-Dlsd_slam_core_DIR指定其路径。

3.3 常见编译错误与修复方案

在Ubuntu 18.04上,你很可能会遇到以下几个经典错误:

错误1:fatal error: Eigen/Core: No such file or directory原因:CMake没有正确找到Eigen3的头文件路径。解决

  • 确保已安装libeigen3-dev
  • 在CMake命令中显式指定路径:-DEIGEN3_INCLUDE_DIR=/usr/include/eigen3
  • 如果Eigen安装在非标准路径,需要相应修改。

错误2:error: ‘CV_LOAD_IMAGE_GRAYSCALE’ was not declared in this scope原因:这是OpenCV版本兼容性问题。CV_LOAD_IMAGE_GRAYSCALE是OpenCV 2.x的宏,在OpenCV 3.x和4.x中已被cv::IMREAD_GRAYSCALE取代。解决:需要修改源代码。在报错的文件中(通常是ImageSource.cppIOWrapper/OpenCV/ImageSource_OpenCV.cpp),找到使用CV_LOAD_IMAGE_GRAYSCALE的地方,将其替换为cv::IMREAD_GRAYSCALE。同时,需要包含正确的头文件#include <opencv2/imgcodecs.hpp>。这是一个典型的针对新系统适配老代码的修改。

错误3:Pangolin相关链接错误,如undefined reference to ‘pangolin::’原因:链接器找不到Pangolin库。可能因为Pangolin没有正确安装,或者CMake没有找到。解决

  • 确认Pangolin已通过sudo make install安装到系统目录(/usr/local)。
  • 尝试在CMake时清除缓存重新配置:删除build目录,重新执行cmake
  • 可以尝试手动指定Pangolin路径:cmake .. -DPangolin_DIR=/usr/local/lib/cmake/Pangolin

错误4:error: ‘usleep’ was not declared in this scope原因usleep函数在较新的C++标准或特定系统上需要特定的头文件。解决:在报错的源文件开头添加头文件#include <unistd.h>

4. 运行测试与数据准备

编译成功后,我们终于可以运行LSD-SLAM了。它需要一个图像序列作为输入。

4.1 获取测试数据集

LSD-SLAM官方提供了一些测试数据集。一个常用的室内场景是desk序列。我们可以从TUM的服务器下载:

cd ~/lsd_slam_ws wget https://vision.in.tum.de/rgbd/dataset/freiburg1/rgbd_dataset_freiburg1_desk.tgz tar -xzvf rgbd_dataset_freiburg1_desk.tgz

解压后会得到一个包含rgb/(彩色图像)和depth/(深度图,LSD-SLAM单目版本不需要)的文件夹,以及一个rgb.txt文件,里面记录了图像的时间戳和文件名。

4.2 运行LSD-SLAM

运行LSD-SLAM通常需要启动两个程序:一个是核心的SLAM节点(lsd_slam_core),另一个是可视化界面(lsd_slam_viewer)。它们之间通过ROS或简单的网络接口通信。由于我们可能没有安装ROS,LSD-SLAM自带了一个基于TCP的通信方式。

第一步:启动可视化器在一个终端中,进入lsd_slam_viewer的编译目录并运行:

cd ~/lsd_slam_ws/src/lsd_slam/lsd_slam_viewer/build ./bin/lsd_slam_viewer

如果一切正常,会弹出一个黑色的Pangolin窗口。这表明可视化部分启动成功,正在等待SLAM核心发送数据。

第二步:运行SLAM核心并指定数据集打开另一个终端,进入lsd_slam_core的编译目录,运行主程序并指定数据集路径和关联文件:

cd ~/lsd_slam_ws/src/lsd_slam/lsd_slam_core/build ./bin/lsd_slam_dataset ~/lsd_slam_ws/rgbd_dataset_freiburg1_desk/rgb/ ~/lsd_slam_ws/rgbd_dataset_freiburg1_desk/rgb.txt
  • 第一个参数是图像目录的路径。
  • 第二个参数是图像关联文件(rgb.txt)的路径。

程序开始运行后,你会在终端看到它读取图像、初始化、跟踪位姿的输出信息。同时,在可视化器窗口中,你应该能看到:

  1. 左侧:当前相机拍摄的图像。
  2. 右侧:重建出的半稠密点云地图和估计的相机轨迹(通常是一条逐渐增长的线)。

4.3 运行参数解析与调整

lsd_slam_dataset程序可以接受一些命令行参数来调整行为:

  • -calib [文件]:指定相机标定文件。如果数据集文件夹内有camera.txt,程序会自动读取。如果没有,你需要准备一个。对于TUM数据集,标定参数通常是固定的。你可以创建一个camera.txt文件,内容类似:
Pinhole 525.0 525.0 319.5 239.5 in_width 640 in_height 480

这表示焦距(fx, fy)=525,光学中心(cx, cy)在(319.5, 239.5),图像分辨率640x480。

  • -speed [浮点数]:播放速度因子。1.0表示实时,0.5表示慢速播放,2.0表示快速播放。对于调试,可以从0.5开始。
  • -mode [0/1/2]:运行模式。0=仅从数据集读取,1=处理数据集并输出结果,2=使用外部图像源。

运行命令可以整合为:

./bin/lsd_slam_dataset -calib ~/lsd_slam_ws/rgbd_dataset_freiburg1_desk/camera.txt -speed 0.5 ~/lsd_slam_ws/rgbd_dataset_freiburg1_desk/rgb/ ~/lsd_slam_ws/rgbd_dataset_freiburg1_desk/rgb.txt

5. 深度问题排查与性能优化

即使程序成功运行,你可能还会遇到跟踪丢失、地图漂移、重建效果差等问题。这部分分享一些进阶的排查和优化经验。

5.1 运行时常见问题与诊断

问题1:可视化器黑屏或闪退,核心程序报错Failed to connect to viewer诊断:两个进程之间的网络通信失败。LSD-SLAM默认使用本地回环地址(127.0.0.1)和特定端口通信。解决

  • 确保先启动lsd_slam_viewer,再启动lsd_slam_core
  • 检查是否有防火墙规则阻止了本地进程间通信(在Ubuntu上通常不会)。
  • 可以尝试在运行核心程序时指定主机和端口(但需要查看源码是否支持该参数,通常不支持修改)。最根本的解决方法是检查lsd_slam_coreIOWrapper/目录下的网络通信代码,确认端口号(默认可能是5000)是否被占用。

问题2:跟踪很快丢失,终端大量输出TRACKING LOST诊断:这是直接法SLAM的常见问题。原因可能是:

  1. 相机运动过快:图像间变化太大,直接法基于灰度不变假设,无法找到正确的像素对应关系。
  2. 光照变化剧烈:数据集中有光照突变,违反了灰度不变假设。
  3. 图像模糊:相机对焦不准或运动导致模糊。
  4. 相机标定参数错误:内参不准确会严重影响位姿估计。解决
  • 使用-speed 0.2更慢地播放数据集,给算法更多处理时间。
  • 检查camera.txt标定文件,确保参数与数据集匹配。TUM RGB-D数据集的标定参数可以在其官网找到。
  • 尝试其他运动更缓慢、光照更稳定的数据集序列。

问题3:重建的地图点云非常稀疏或扭曲诊断:深度滤波器收敛不佳或深度值传播有问题。直接法SLAM的地图是“半稠密”的,只在梯度明显的区域计算深度。如果图像纹理较弱,地图就会稀疏。解决

  • 这是算法本身的特性。可以尝试调整源码中DepthEstimation.cppSlamSystem.cpp中的参数,如深度滤波器的初始化方差、收敛阈值等。但修改这些参数需要你对算法有较深理解。
  • 确保输入图像是灰度图。虽然程序通常会自动转换,但最好确认一下。

5.2 关键源码参数调整(进阶)

如果你想深入优化或适应自己的场景,可能需要修改源码。这里列举几个关键文件和作用:

  • lsd_slam_core/SlamSystem.h/.cpp:整个SLAM系统的总控,可以调整跟踪、建图、回环检测的开关和主要参数。
  • lsd_slam_core/DepthEstimation.cpp:深度估计的核心,修改深度滤波器参数(如MIN_GOODPERGOODBAD_PIXEL)会影响深度点的生成和收敛速度。
  • lsd_slam_core/Tracking/TrackingReference.cpp:跟踪参考帧的管理,影响跟踪的鲁棒性。
  • CMakeLists.txt:可以修改编译优化等级(如-O3)、添加调试信息(-g)或启用SSE等指令集加速。

修改示例:提高跟踪鲁棒性Tracking/TrackingReference.cpp中,有一个函数负责选择用于跟踪的关键点。你可以尝试降低梯度阈值,让算法在纹理稍弱的区域也能提取到点,但这可能会增加计算量和噪声。修改需谨慎,每次只改一个参数并观察效果。

5.3 使用ROS运行LSD-SLAM(可选扩展)

原始的LSD-SLAM也提供了ROS功能包。如果你在Ubuntu 18.04上安装了ROS Melodic,可以尝试用ROS来运行,这样能更方便地连接真实的相机(如USB摄像头或RGB-D相机如Kinect)。

  1. 安装ROS Melodic:按照ROS官网指引安装完整版或基础版。
  2. 创建ROS工作空间并编译
    mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src # 假设你把lsd_slam源码放在这里 cp -r ~/lsd_slam_ws/src/lsd_slam ./ cd ~/catkin_ws catkin_make -j$(nproc)
    注意,ROS版本的代码可能需要额外的依赖,如ros-melodic-libg2o。编译时可能会遇到更多兼容性问题,需要根据错误信息逐一解决。
  3. 运行:使用roslaunch lsd_slam_core live.launch等命令启动。

ROS方式集成度更高,但环境配置更复杂,更适合与真实的机器人系统对接。对于初次接触,建议先从非ROS的数据集版本入手。

6. 项目总结与延伸思考

在Ubuntu 18.04上成功部署LSD-SLAM,就像完成了一次经典的软件考古与工程实践。这个过程里,你不仅是在安装一个程序,更是在梳理一个复杂C++项目的依赖脉络,学习如何解决跨版本的编译兼容性问题,并直观感受直接法SLAM的优缺点。

从我多次部署的经验来看,耐心和系统化排查是关键。不要被一长串的错误信息吓倒,按照“检查依赖->修正源码->调整编译选项”的流程,大部分问题都能解决。那个CV_LOAD_IMAGE_GRAYSCALE错误,几乎是所有在老系统上编译OpenCV 2时代项目的“必修课”。而Pangolin的编译,则是对你系统图形开发库是否完整的一次检验。

运行起来之后,观察LSD-SLAM的重建结果,你会发现它和ORB-SLAM这类特征点法有很大不同。它的地图是半稠密的,带有梯度信息的像素点才有深度值,这导致地图看起来像一幅“素描”。它的优势在于能够直接利用所有像素信息,在纹理丰富的区域理论上更稠密,且对模糊、快速运动有一定容忍度。但劣势也很明显:严重依赖灰度不变假设,对光照变化极其敏感;计算量大;回环检测和全局优化模块相对简单。

因此,把LSD-SLAM在Ubuntu 18.04上跑通,只是一个起点。你可以以此为基地,做很多有趣的事情:

  • 代码走读:结合原论文,深入阅读SlamSystemSE3TrackerDepthEstimation等核心模块的代码,理解直接法跟踪、深度滤波器的实现细节。
  • 性能分析:使用gprofperf工具分析程序热点,看看时间主要消耗在哪个函数(很可能是图像金字塔构建或雅可比矩阵计算)。
  • 算法对比:在同一个数据集上,运行LSD-SLAM和ORB-SLAM2(也需要在Ubuntu 18.04上部署),对比它们的轨迹精度、地图效果和运行速度。
  • 尝试改进:例如,尝试将原始的梯度点选取策略改为基于FAST或Shi-Tomasi角点,看看能否在保持直接法优势的同时提升跟踪鲁棒性。

最后一个小技巧:建议你将整个成功编译的环境(包括修改后的源码、安装的依赖)通过Dockerfile或虚拟机快照保存下来。LSD-SLAM这样的研究工具,我们可能不会频繁使用,但当下次需要复现实验或进行对比时,一个现成的、可工作的环境能节省大量时间。毕竟,在软件世界里,“它能工作”本身就是一种宝贵的状态。