ORB SLAM3 点云地图保存

目前 ORB_SLAM3 已经提供了地图保存功能。

方法是在 yaml 文件中以下这行配置:

System.SaveAtlasToFile: "map.osa"

保存下来的地图可以在下次运行 ORB_SLAM3 时加载。

然而,我经过搜索,没能找到关于 .osa 文件离线加载和可视化的方法,于是对 ORB_SLAM3 的代码进行了简单的修改,使其可以保存 pcd 格式的点云地图。

修改代码的已发布至:GitHub - DioVei/ORB_SLAM3_with_save: Modify the orb-slam3 code to save the keypoints per frame and the map in PCD format.

代码中仅使用到 PCL 基础的点云保存功能,因此应该兼容不同版本的 PCL 库。

sudo apt-get install libpcl-dev pcl-tools

首先,我们找到代码绘制点云的部分,即 src 文件夹下的 MapDrawer.cc 文件。

第一步,先加入 pcl 保存点云所需的头文件:

#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>

第二步,找到 DrawMapPoints 函数中的如下代码:

for(set<MapPoint*>::iterator sit=spRefMPs.begin(), send=spRefMPs.end(); sit!=send; sit++)
{
    if((*sit)->isBad())
        continue;
    Eigen::Matrix<float,3,1> pos = (*sit)->GetWorldPos();
    glVertex3f(pos(0),pos(1),pos(2));

}

将其修改为如下代码:

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_saved(new pcl::PointCloud<pcl::PointXYZ>());
for(set<MapPoint*>::iterator sit=spRefMPs.begin(), send=spRefMPs.end(); sit!=send; sit++)
{
    if((*sit)->isBad())
        continue;
    Eigen::Matrix<float,3,1> pos = (*sit)->GetWorldPos();
    glVertex3f(pos(0),pos(1),pos(2));

    //modified by Awei
    pcl::PointXYZ p;
    p.x = pos(0);
    p.y = pos(1);
    p.z = pos(2);
    cloud_saved->points.push_back(p);
}
if (cloud_saved->points.size())
    pcl::io::savePCDFileBinary("map.pcd", *cloud_saved);

代码修改部分十分简单,最后一步就是在 CMakeLists.txt 中添加 PCL 库:

find_package(PCL REQUIRED)

include_directories(
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/include/CameraModels
${PROJECT_SOURCE_DIR}/Thirdparty/Sophus
${EIGEN3_INCLUDE_DIR}
${Pangolin_INCLUDE_DIRS}
${PCL_INCLUDE_DIRS}
)

target_link_libraries(${PROJECT_NAME}
${OpenCV_LIBS}
${EIGEN3_LIBS}
${Pangolin_LIBRARIES}
${PCL_LIBRARIES}
${PROJECT_SOURCE_DIR}/Thirdparty/DBoW2/lib/libDBoW2.so
${PROJECT_SOURCE_DIR}/Thirdparty/g2o/lib/libg2o.so
-lboost_serialization
-lcrypto
)

最终,保存下来的地图可以使用 pcl_viewer 进行查看:

pcl_viewer map.pcd

提醒读者一下,保存下来的map.pcd是在终端运行命令时所在的路径下的,所以建议各位可以新建一个文件夹,在该文件夹下运行命令,这样方便找到和整理点云地图。


更新

        以上改法是Stereo模式在EuRoC V1_01_easy数据集下不使用ROS测试有效的,最终保存下来的点云地图如下

        但是,后来我也尝试了自己的数据集,并发现在大型数据集下用上面的改法不能保存完整地图,因此代码按照以下方式修改。

        找到以下代码段

for(size_t i=0, iend=vpMPs.size(); i<iend;i++)
{
    if(vpMPs[i]->isBad() || spRefMPs.count(vpMPs[i]))
        continue;
    Eigen::Matrix<float,3,1> pos = vpMPs[i]->GetWorldPos();
    glVertex3f(pos(0),pos(1),pos(2));
}

        将其修改为 

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_saved(new pcl::PointCloud<pcl::PointXYZ>());
for(size_t i=0, iend=vpMPs.size(); i<iend;i++)
{
    if(vpMPs[i]->isBad() || spRefMPs.count(vpMPs[i]))
        continue;
    Eigen::Matrix<float,3,1> pos = vpMPs[i]->GetWorldPos();
    glVertex3f(pos(0),pos(1),pos(2));
        
    //modified by Awei
    pcl::PointXYZ p;
    p.x = pos(0);
    p.y = pos(1);
    p.z = pos(2);
    cloud_saved->points.push_back(p);
}
if (cloud_saved->points.size() > pre_num)
{
    pcl::io::savePCDFileBinary("map.pcd", *cloud_saved);
    pre_num = cloud_saved->points.size();
}

        并在 MapDrawer.cc 开头加入全局变量 pre_num。

extern int pre_num = 0;

        另外,若不想每一关键帧都覆盖掉原来的map.pcd,则可以将KeyFrame ID传入MapDrawer::DrawMapPoints()函数,以ID作为文件名进行保存,此处不贴出代码,读者可以找到调用该函数的地方进行修改。

ORB-SLAM3是一种先进的实时单目SLAM(Simultaneous Localization and Mapping)系统,可以在未知的环境中同时定位相机位置并构建三维地图。这个系统具有很多的应用领域,比如无人机导航、增强现实、机器人导航等。 当使用ORB-SLAM3系统进行地图保存时,有几个主要的步骤。首先,需要打开相机并获取图像数据。然后,利用ORB特征提取和描述子生成算法,从图像中提取特征点。接下来,使用初始滤波器来剔除不好的特征点,提高地图的质量。然后,通过移动相机来获取多帧图像,通过ORB特征匹配算法来估计相机之间的运动。 在地图构建的过程中,ORB-SLAM3系统会将特征点在三维空间中进行三角化,从而得到点云数据。同时,它会通过关键帧选择算法,选择一些重要的帧作为关键帧来构建地图。通过使用优化算法,ORB-SLAM3能够进一步优化地图的精度和一致性。 最后,在地图构建的过程中,ORB-SLAM3系统会实时地保存地图数据。这些地图数据包括特征点的位置、帧之间的相对运动、点云数据等。这些数据可以通过文件系统或者数据库来进行保存。 总体而言,ORB-SLAM3系统可以实时地构建和保存三维地图,具有广泛的应用潜力。它在地图构建的过程中使用了多种先进的算法和技术,保证了地图的精度和一致性。同时,它也提供了保存地图数据的功能,方便后续的应用和分析。
评论 51
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值