在Ubantu22.04中运行ORB_SLAM3并进行源码解析
1.ORB_slam3简介
ORB-SLAM3 是一款前沿的即时定位与建图(SLAM)系统,专为大规模环境下的实时定位与三维重建设计。系统兼容多种视觉传感器配置,包括单目、立体双目以及RGB-D相机。ORB-SLAM3 采用 Oriented FAST 和 Rotated BRIEF(ORB)算法进行特征点检测与匹配,确保了在复杂场景下的高度准确性和稳健性。本文将在香橙派AIpro的环境下运行这些内容。
2.安装并调试ORB_SLAM3
(1)下载源码
git clone https://github.com/UZ-SLAMLab/ORB_SLAM3.git
运行这个命令会有一个名为ORB_SLAM3的文件夹
(2)安装依赖
① Pangolin
git clone --recursive https://github.com/stevenlovegrove/Pangolin.git
等待下载完成后
cd Pangolin sudo ./scripts/install_prerequisites.sh cmake -B build cmake --build build -t pypangolin_pip_install
② opencv
由于香橙派的系统自带opencv环境,所以不需要安装,但是需要安装相对应的python环境,首先需要知道安装的opencv版本,使用以下命令:
Pkg-config --modversion opencv4
我的版本是4.5.4,故使用以下命令安装opencv-python
pip install opencv-python==4.5.4.64
③ Eigen3
香橙派的系统自带这个,如果没有可以通过以下命令来安装:
git clone https://github.com/eigenteam/eigen-git-mirror
安装
cd eigen-git-mirror mkdir build cd build cmake .. sudo make install
(3)编译
首先修改CMakelist.txt文件,在头部加入以下代码
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON)
由于build.sh中包括make命令,但是香橙派AIpro采用4核8线程故采用 make -j 8来加快速度。使用以下命令 将make部分的代码修改为make -j 8:
cd ORB_SLAM3 sudo gedit build.sh
然后运行以下命令
cd ORB_SLAM3 chmod +x build.sh ./build.sh
(4)测试
选择合适的测试集进行测试,使用以下命令安装TUM测试集:
mkdir -p TUM/rgbd_dataset_freiburg1_xyz
cd TUM/rgbd_dataset_freiburg1_xyz
wget https://vision.in.tum.de/rgbd/dataset/freiburg1/rgbd_dataset_freiburg1_xyz.tgz
tar -xzvf rgbd_dataset_freiburg1_xyz.tgz
rm rgbd_dataset_freiburg1_xyz.tgz
由于我安装时associate.txt为空,所以需要加一个python代码来写入associate.txt,安装以下步骤:
touch associate.py sudo gedit associate.py
然后写入以下代码:
点击查看代码
#!/usr/bin/env python3
import sys
def read_file_list(filename):
with open(filename) as f:
lines = f.readlines()
list = []
for line in lines:
if line[0] == "#":
continue
line = line.strip().split()
if len(line) < 2:
continue
list.append((float(line[0]), line[1]))
return list
def associate(first_list, second_list, offset, max_difference):
matches = []
second_list = [(b + offset, a) for a, b in [(a, float(b)) for a, b in second_list]]
second_dict = dict(second_list)
for a, b in first_list:
best_match = None
best_diff = float("inf")
for c in second_dict:
diff = abs(a - c)
if diff < best_diff:
best_diff = diff
best_match = c
if best_diff < max_difference:
matches.append((a, b, second_dict[best_match]))
matches.sort()
return matches
if len(sys.argv) < 3:
print("Usage: associate.py first_file second_file [offset] [max_difference]")
sys.exit(1)
first_file = sys.argv[1]
second_file = sys.argv[2]
offset = 0.0
if len(sys.argv) > 3:
offset = float(sys.argv[3])
max_difference = 0.02
if len(sys.argv) > 4:
max_difference = float(sys.argv[4])
first_list = read_file_list(first_file)
second_list = read_file_list(second_file)
matches = associate(first_list, second_list, offset, max_difference)
for a, b, c in matches:
print(a, b, c)
写入完成后运行这个命令:
Python3 associate.py TUM/rgbd_dataset_freiburg1_xyz/rgb.txt TUM/rgbd_dataset_freiburg1_xyz/depth.txt > TUM/rgbd_dataset_freiburg1_xyz/associate.txt
最后运行这个命令:
./Examples/RGB-D/rgbd_tum Vocabulary/ORBvoc.txt Examples/RGB-D/TUM1.yaml TUM/rgbd_dataset_freiburg1_xyz TUM/rgbd_dataset_freiburg1_xyz/associate.txt
演示效果如下:
(5)使用ORB_slam3调用奥比中光gemini pro
在ORB_slam3文件夹下创建任意一个文件夹,随便取名字,我的文件夹名称为cam_ws,这次先不调用它的深度功能,在cam_ws中创建3个文件,分别为run_slam.cpp,CMakelist.txt以及Setting.yml
首先在ORB_slam3的examples文件夹中找到TUM1.yaml并且复制到cam_ws上改名为Setting.yaml
然后把以下代码复制到run_slam.cpp上
点击查看代码
#include <opencv2/opencv.hpp>
include <opencv2/opencv.hpp>
#include "System.h
int main(int argc, char **argv) {
if (argc != 3) {
std::cerr << "Usage: ./run_slam path_to_vocabulary path_to_settings" << std::endl;
return 1;
}
// Initialize ORB_SLAM3 system
ORB_SLAM3::System SLAM(argv[1], argv[2], ORB_SLAM3::System::MONOCULAR, true);
// Open camera
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "Error: Unable to open camera" << std::endl;
return 1;
}
cv::Mat frame;
while (cap.read(frame)) {
SLAM.TrackMonocular(frame, cv::getTickCount());
// Display the frame
cv::imshow("Frame", frame);
if (cv::waitKey(1) == 27) {
break; // Stop the loop if 'Esc' key is pressed
}
}
// Stop all threads
SLAM.Shutdown();
return 0;
}
再把以下代码复制到CMakelist.txt上:
点击查看代码
cmake_minimum_required(VERSION 3.10)
project(run_slam)
find_package(OpenCV REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(Pangolin REQUIRED)
include_directories(
${OpenCV_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
${Pangolin_INCLUDE_DIRS}
/home/HwHiAiUser/ORB_SLAM3/include
/home/HwHiAiUser/ORB_SLAM3
/usr/include/eigen3
/home/HwHiAiUser/ORB_SLAM3/Thirdparty/Sophus
/home/HwHiAiUser/ORB_SLAM3/include/CameraModels
)
add_executable(run_slam run_slam.cpp)
target_link_libraries(run_slam
${OpenCV_LIBS}
${EIGEN3_LIBS}
${Pangolin_LIBRARIES}
/home/HwHiAiUser/ORB_SLAM3/lib/libORB_SLAM3.so
)
最后再建一个build文件夹,运行以下程序:
cmake ..
build -j4
然后再通过以下shell指令实现调用:
./run_slam /path/to/ORBvoc.txt /path/to/Settings.yaml
/path/to是你的文件夹位置,结果图如下:
3.ORB_slam3源码解析
(1)源代码结构概览
ORB-SLAM3 的源代码经过精心设计,分为多个核心组件:
① 主程序:程序的入口点,负责初始化和调度。
② 跟踪模块:处理相机位姿估计和特征点追踪。
③ 局部映射:管理局部地图的构建与优化。
④ 闭环检测:执行循环闭合检测及相应的地图优化。
⑤ 可视化工具:提供图形界面展示系统状态。
⑥ 工具箱:集合了一系列辅助函数和通用模块。
(2)系统架构解析
① 输入模块
系统接受来自单目、双目及RGB-D相机的视觉输入,配合IMU数据,通过ORB算法提取特征点,而IMU数据则用于运动补偿,提高位姿估计的准确性。
② 跟踪模块
ORB-SLAM3 的 跟踪模块 在原有基础上融入了IMU数据处理,不仅提高了位姿估计的实时性,还增强了系统的鲁棒性。模块能实时计算当前帧在地图中的位姿,并智能判断是否将当前帧标记为关键帧,对于视觉惯性模式,通过融合惯性测量单元的信息,优化位姿估计,当跟踪丢失时,系统能在地图集内寻找重定位机会,必要时切换激活地图,确保系统的连续运行。
③ 局部建图模块
局部建图模块 负责将关键帧和地图点整合至当前激活地图中,通过视觉或视觉惯性束调整(BA)技术优化地图,确保地图的精准度与效率。
④ 闭环检测与地图合并
闭环检测与地图合并模块 在系统中扮演重要角色,它持续监测新加入的关键帧,一旦发现闭环,立即执行闭环校正或地图融合,维持地图的全局一致性。
⑤ Atlas【地图集】模块
Atlas 模块作为多子图系统,由多个独立的地图构成。当前帧所在地图为激活地图,当跟踪失败时,该地图转为非激活状态,系统随即初始化新的激活地图,保证系统的持续运作。Atlas 模块维护着一个激活地图供跟踪模块使用,同时局部建图模块依据新关键帧信息持续优化地图。此外,Atlas 中还包括未激活地图,整个系统利用词袋模型构建关键帧信息库,用于地图的重定位、闭环检测和融合。
(3)源码解析
① 主程序启动流程
在 main.cc 文件中,系统启动流程如下所示:
点击查看代码
int main(int argc, char **argv)
{
// 初始化ROS环境
ros::init(argc, argv, "orb_slam3");
ros::NodeHandle nh;
// 创建SLAM系统实例
ORB_SLAM3::System SLAM(vocabularyFile, settingsFile, ORB_SLAM3::System::STEREO, true);
// 设置图像与IMU数据的抓取器
ImageGrabber ig(nh, &SLAM);
// 订阅图像和IMU数据流
ros::Subscriber subImgs = nh.subscribe("/camera/image_raw", 1, &ImageGrabber::GrabStereo, &ig);
ros::Subscriber subImu = nh.subscribe("/imu/data", 1, &ImageGrabber::GrabImu, &ig);
// 主循环
while(ros::ok())
{
ros::spinOnce();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// 关闭SLAM系统
SLAM.Shutdown();
return 0;
}
② 特征检测与匹配
特征检测与匹配发生在 Tracking 模块中,具体通过 ORBextractor 类和 Matcher 类实现:
点击查看代码
class Tracking
{
public:
void TrackMonocular(const cv::Mat &im, const double &timeStamp);
private:
ORBextractor *mpORBextractor;
Matcher *mpMatcher;
};
③ 姿态估计与跟踪
Track() 函数负责姿态估计与跟踪,实现如下:
点击查看代码
void Tracking::TrackMonocular(const cv::Mat &im, const double &timeStamp)
{
// 初始化位姿估计
// 特征点的跟踪
// 基于优化算法对当前帧的位姿进行精调
// 更新局部地图
// 评估跟踪效果
}
④ 局部地图管理
LocalMapping 模块的 Run() 函数持续处理新加入的关键帧:
点击查看代码
class LocalMapping
{
public:
void Run();
private:
// ...其他成员变量...
};
具体实现中会调用 InsertKeyFrame() 和 UpdateMap() 方法来管理地图点和关键帧。
⑤ 闭环检测与地图优化
点击查看代码
LoopClosing 模块通过 Run() 函数持续运行,检测闭环并优化地图:
class LoopClosing
{
public:
void Run();
private:
// ...其他成员变量...
};
⑥ 可视化与监控
Viewer 类的 Run() 方法实现了对系统状态的实时监控:
点击查看代码
class Viewer
{
public:
void Run();
private:
// ...其他成员变量...
};
此方法利用OpenGL技术展示3D视图,让用户直观了解SLAM系统的运行状态。
以上代码片段仅为简化示例,实际应用中,每个类和方法都有更复杂的内部实现。
(4)结论与展望
ORB-SLAM3 以其模块化的架构,实现了高效、精确的特征点检测、跟踪、局部地图管理和闭环检测。通过对核心源码的解析,我们深入了解了其工作原理,包括但不限于主程序启动流程、特征检测与匹配、姿态估计与跟踪、局部地图管理、闭环检测与地图优化,以及可视化工具的运用。未来,ORB-SLAM3 有望在计算机视觉和机器人技术领域发挥更为重要的作用,通过持续的技术革新和应用场景拓展,推动SLAM系统性能的不断提升。