一、概述
因为要使用一种视觉SLAM算法完成作业,我们选择使用比较广泛的ORB-SLAM方法,在Ubuntu20.04上,使用ros-noetic版本进行配置。在配置并运行过程中,我们遇到了比较多的困难,利用博客记录一下我们所遇到的困难和解决方法。
二、具体配置过程
(一)一些依赖库的配置
ORB-SLAM3主要依赖于OpenCV、g2o、DBoW2、Sophus、OpenGL、GLEW等。其中OpenCV需要手动安装.
1.g2o、DBoW2、Sophus这三个
第三方库在ORB-SLAM的源代码中已经携带上,如图所示。具体在Thirdparty里面。也不需要手动编译,后面编译时候,build.sh里面有着些库的编译。
2.OpenGL、GLEW和Pangolin
OpenGL、GLEW这两个安装 ,可以参考其他博客。
Pangolin的安装比较简单,在github下载源代码。在终端中输入如下的命令
mkdir build
cd build
cmake ..
make
sudo make install
3.OpenCV安装
OpenCV需要特别注意版本问题,博客是根据OpenCV3.2版本进行实现的,比较新的OpenCV版本例如4.8.0和4.9.0没有尝试过。4.8.0尝试过,但在我的电脑上没有配置成功,日后有时间,准备再尝试一下新版本的OpenCV,个人感觉是可以的,因为在ORB-SLAM3的CMakeList.txt文件中,其查询的OpenCV包已经是4.4版本了。在官方网站上,如图所示,其标注过4.4版本是经过测试可以实现的,但为了可能在ROS进行配置,我们还是选择低版本的3.2进行配置。
OpenCV的安装和卸载比较简单,在build文件夹下,输入如下命令,表示安装。
sudo make install
输入如下命令
sudo make uninstall
如果在当初编译时候,是在build文件夹下进行的话,直接在终端中输入就行。在这两个文件存在位置打开终端就行。
需要特别注意安装OpenCV版本的问题,因为不同版本的OpenCV可能会报出不同的错误,我在做的使用首先使用的OpenCV4.8.0版本,发现有报错。后来换成OpenCV3.2.0进行尝试。原版本使用的是OpenCV3.0,在我的电脑上安装不上去。
(二) cv_bridge问题,段错误解决
因为ROS的图像消息,需要通过cv_bridge与OpenCV能够处理的信息进行转化,由于ROS在下载时候,其本身会携带OpenCV库,在编译时候,会自动查找到ROS携带的OpenCV库,无法将编译的文件链接到我们手动安装的库。
这个会导致之后运行ROS包的时候一个错误,如图所示,即段错误。这个错误是因为源代码中这个地方导致的,以单目相机为例。这个地方在Examples/ROS/ORB-SLAM3/src/ros_mono.cc文件中。这个地方最终会导致段错误的发生。知道问题发生在这个地方是因为,我将每行代码进行注释来观察,发现在这行代码存在时候,系统会报出段错误。
cv_ptr = cv_bridge::toCvShare(msg);
解决这个问题可以参考这篇博客,其详细介绍了几种方法用来解决自己安装的OpenCV和ROS自带的OpenCV的指向问题。 作者使用的是他提到的第四种方法实现的,前三种方法他在博客结尾也全部都指出实现方法。我采用这篇博客作者所提到的第三种方法,即将ROS原来的cv_bridge给删除,重新在github上下载源代码,手动进行编译,安装。
Ubuntu系统运行ORB_SLAM3报段错误(核心已转储)_ubuntu(核心已转储)怎么解决-CSDN博客
操作是首先将原本的cv_bridge删除,在终端输入如下的命令,删除原来的。
sudo apt-get remove ros-noetic-cv-bridge
在github(GitHub - ros-perception/vision_opencv)上下载自己安装的ROS版本相对应的cv_brideg版本,如图所示。
下载完成后,在cv_brideg文件夹下,找到他的CMakeList.txt文件。在与OpenCV相关的find_package进行修改。将其更改为如下所示,将其设置为我们自己下载安装的版本。
set(_opencv_version 3.2)
find_package(OpenCV 3.2 QUIET)
if(NOT OpenCV_FOUND)
message(STATUS "Did not find OpenCV 4, trying OpenCV 3")
set(_opencv_version 3)
endif()
之后再终端中输入如下的命令,将其编译并安装。
mkdir build
cd build
cmake ..
make -j8
sudo make install
安装的文件在/usr/local/share/下,如图所示
我们还需要将这个cv_bridge这个文件夹放置在ROS-noetic目录下,具体目录为/opt/ros/noetic/share/
这里复制文件夹需要使用sudo命令。复制是为了之后使用ROS编译时候,可以查询到我们自己通过源代码下载编译安装的cv_bridge。
(三)编译ORB-SLAM3
要通过ROS运行ORB-SLAM我们需要一些ORB-SLAM3的依赖,所以需要首先编译ORB-SLAM3,在终端中输入如下命令。第一条是添加可执行权限,第二条是运行这个文件。
chmod +x build.sh
./build.sh
因为需要编译的文件较多,这个时间可能比较漫长,需要耐心等待。中间可能会遇到一些报错。这里我整理了一些我遇到的问题的报错。
1.se.hpp文件查询不到
如图所示,这里我们选择及其简单粗暴的方式,直接在头文件中将其绝对路径放进去让编译器查找这个文件,不怕他找不到。
2.Sophus重定义问题
如图所示,这里报出redefinition of 'struct Sophus::Constants<Scalar>',翻阅终端中全部编译信息,发现设计redefinition的报错不少。导致这个问题是因为,我们之前下载过Sophus并安装过,在ORB-SLAM中,其在第三方库中也有,这个地方冲突了。我们选择将我们原来下载的Sophus库进行删除。
删除方法可以在网络上进行查找。
3. 其余
其余可能还有些别的问题,但是我忘记截图报错,因为弄了一天,心情比较崩溃,但所有报错均可以在网络上查找到,有详细的博客讲解具体如何解决。
(四)在ROS中实现ORB-SLAM
1.概述
可以参考这篇博客,我的实现方法是根据这篇博客的改编。ubuntu20.04通过ros-noetic配置ORBslam3_ubuntu20.04编译orbslam3ros-CSDN博客
这里需要说明,在ORB-SLAM3自身带有build_ros.sh文件,这个是构建ROS文件的,但是这个文件需要修改。因为在ORB-SLAM中ROS被放置在Examples_old中,而build_ros.sh文件中依旧是写的Examples,不对应,需要进行更改。
但由于ORB-SLAM3的更新时间已经是好几年前,直接运行这个文件是无法在我的ROS-noetic环境下编译通过的,会报出来不少错误。要运行的话,方法跟build.sh一致,如下所示。
chmod +x build_ros.sh
./build_ros.sh
可以尝试一下能否运行成功,我这里是无法运行成功的,不知道其余是否可以。这里我选择将其改写,这里仅以单目为例。
2.创建工作空间
在ORB-SLAM3-master文件夹,即刚才编译的那个整个文件夹下输入如下命令。
mkdir -p ros/src
cd ros
catkin_make
创建功能包myorbslam3,并添加如下依赖sensor_msgs、cv_bridge、roscpp、image_transport、std_msgs、geometry_msgs这些,命令如下
catkin_create_pkg myorbslam3 sensor_msgs cv_bridge roscpp image_transport std_msgs geometry_msgs
返回到ros目录下,重新进行catkin_make,观察是否报错,如果报错,证明有些依赖名称写错,需要进行检查。
3.编写cpp文件
空间创建好之后,我们在创建的包的src目录下创建文件,名字为testorb.cpp。这个cpp文件主要的不同是,我们不在通过终端输入参数,直接将参数写在cpp文件内。
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include "System.h"
#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <chrono>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
// 设置参数文件和字典文件
string paramterfile = "/home/gfc/study_BIT/need_lib/ORB_SLAM3-master/ros/src/myorbslam3/config/myslam.yaml";
string vocFile = "/home/gfc/study_BIT/need_lib/ORB_SLAM3-master/Vocabulary/ORBvoc.txt";
class ImageGrabber
{
public:
ImageGrabber(ORB_SLAM3::System* pSLAM):mpSLAM(pSLAM){}
void GrabImage(const sensor_msgs::ImageConstPtr& msg);
ORB_SLAM3::System* mpSLAM;
};
void ImageGrabber::GrabImage(const sensor_msgs::ImageConstPtr& msg)
{
// cout << "hahaha" << endl;
cv_bridge::CvImageConstPtr cv_ptr;
try
{
cv_ptr = cv_bridge::toCvShare(msg);
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("cv_bridge exception: %s", e.what());
return;
}
mpSLAM->TrackMonocular(cv_ptr->image,cv_ptr->header.stamp.toSec());
}
int main(int argc, char *argv[])
{
// 声明系统
ORB_SLAM3::System SLAM(vocFile, paramterfile, ORB_SLAM3::System::MONOCULAR, true);
// 初始化ros节点
ros::init(argc, argv, "Mono");
ros::start();
ImageGrabber igb(&SLAM);
ros::NodeHandle nodeHandler;
ros::Subscriber sub = nodeHandler.subscribe("/usb_cam/image_raw", 1, &ImageGrabber::GrabImage, &igb);
ros::spin();
return 0;
}
主要订阅话题名称,需要进行匹配。这里需要重点检查cv_bridge是否安装正确,否则会报错。
4.配置CMakeList.txt文件
这里需要主要链接库的设置,尤其是opengl和GLEW,需要配置cv_bridge使找到正确的cv_bridge位置。
cmake_minimum_required(VERSION 3.0.2)
project(myorbslam3)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3")
set(ORBSLAM_PATH "/home/gfc/study_BIT/need_lib/ORB_SLAM3-master/")
set(cv_bridge_DIR /usr/local/share/cv_bridge/cmake)
find_package(OpenCV REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(Pangolin REQUIRED)
# 查找GLEW库
find_package(GLEW REQUIRED)
find_package(catkin REQUIRED COMPONENTS
cv_bridge
geometry_msgs
image_transport
nav_msgs
rosbag
roscpp
rospy
sensor_msgs
std_msgs
tf
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES myorbslam3
CATKIN_DEPENDS cv_bridge geometry_msgs image_transport nav_msgs rosbag roscpp rospy sensor_msgs std_msgs tf
# DEPENDS system_lib
)
## include
include_directories(
${catkin_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIRS}
${Pangolin_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}
${ORBSLAM_PATH}
${ORBSLAM_PATH}/include
${ORBSLAM_PATH}/include/CameraModels
${Pangolin_INCLUDE_DIRS}
${GLEW_INCLUDE_DIRS}
# ${OPENGL_INCLUDE_DIR}
${catkin_INCLUDE_DIRS}
)
## libs
set(LIBS
${OpenCV_LIBS}
${EIGEN3_LIBS}
${Pangolin_LIBRARIES}
${ORBSLAM_PATH}/Thirdparty/DBoW2/lib/libDBoW2.so
${ORBSLAM_PATH}/Thirdparty/g2o/lib/libg2o.so
${ORBSLAM_PATH}/lib/libORB_SLAM3.so
${OPENGL_LIBRARIES}
${GLEW_LIBRARIES}
-lboost_system
)
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(testorb src/testorb.cpp)
## Specify libraries to link a library or executable target against
target_link_libraries(testorb
${catkin_LIBRARIES}
${LIBS}
)
配置完成后,即可进行编译运行。
5.运行
启动roscore之后,可以启动相机,或者rosbag包都可以显示,但是需要注意,ORB-SLAM初始化的问题,他需要初始化才可以显示,初始化可以用小的平移来实现,同时,在运行时候,车速可以低一些,太高算不过来。
如图所示,显示了正确运行。