自从上一个单目AR系统做完后,就仔细思考了一下我到底在做什么,接下来要做什么。之前博客上写的是3d重建,后来视野开阔了之后发现无论我做3d重建,SLAM,AR,重要的都是姿态更新。一个精准的稳定的姿态更新,决定着系统的好坏。贝叶斯滤波器(EKF扩展卡尔曼滤波,PF粒子滤波)和通用图优化(G2O)是使得姿态更加精准稳定的两种方法。近些年来G2O在视觉SLAM领域逐渐成为了主流的后端优化方法。 具体的视觉SLAM流程和G2O的相关知识,我将在模块《关于SLAM的那些事》里的接下来两篇文章中讲到(包括自己优化的一些代码)。本篇博客主要讲一下G2O在windows环境下的搭配。为什么要选windows,因为这些年一直用的是vs的编辑器(vc++6.0,vs2012,vs2013),对于这个熟悉的领域突然换到ubuntu下使用cmake还是有点不适应的(尽管这么说,我还是推荐做学术的童鞋多用用linux系统如ubuntu,各种库真的很方便而且能学到很多东西)。言归正传,接下来讲一下开发win32程序和x64程序的G2O的环境搭配(win32使用橘黄色字体,x64使用粉色字体,大家可以根据需求跳着看)。
首先放一张G2O官方github的windows编译的步骤图以及G2O源码的下载链接:
一共6个步骤:编译Eigen,安装Qt,编译libQGVLiewer,Cmake编译g2o,VS2013生成g2o,添加环境变量并开始使用。不需要g2o_viewer.exe来查看优化结果的不需要qt和libqgliewer(我觉得一般人都需要)。在ubuntu下还需要suitesparse但是windows不需要(其实EXTERNAL中有csparse)。
1.编译Eigen3.2.7
这个步骤在我的PCL编译中有详细讲解(32位)。
这里简单展示下64位的cmake和vs编译结果:
2.安装Qt5.5.1
这里我们安装的是5.5.1的32位和64位的版本。大家也可以下载Qt4和Qt5的其他版本,都是可行的。注意下载的时候选择离线安装包里的windows主机下面的。有一个点要强调一下,要开发win32程序,程序中用到的所有lib和dll都需要是32位的,要开发x64程序,程序中用到的所有lib和dll都需要是64位的。include就无所谓了都一样。为什么要开发64位的程序呢,因为32位的程序在64位的win7,win8,win10系统里最大只能使用4G内存(微软官方说明,使用IMAGE_FILE_LARGE_ADDRESS_AWARE设置),而64位的程序可以使用高达几百G的内存。当然有小伙伴要说怎么可能使用那么多的内存,肯定存在内存泄漏问题,但是我还是想说,在内存管理得当的基础上,内存越大,我们能做的事越多。下载完成后分别安装,并用容易区分的名字命名(当然也可以只下载安装大家需要的位数的版本):
大家可以使用cmd输入qmake -v来查看qt是否安装成功。
接下来安装vs2013的QT插件(其他下载 中的 Visual Studio Add-in 1.2.4 for Qt5 (156 MB)),可以在vs中打开qt的工程(如下一步中的libQGLViewer.pro):
当然也可以用qt creator打开编译,但是我的C盘user中的用户名是中文,而creator编译过程中产生的临时变量在C:\Users\柴\AppData中老是识别不了中文,报错,而我不太熟悉qt creator所以经过尝试没有解决于是使用了vs的插件来打开编译qt工程。下载安装好之后打开vs2013,左上角可以看到QT5,开发选项:
添加刚才安装的qt版本的name和path。name自己决定,path按照下图中的写:
(注意图中下方的默认版本设置比较重要,下一步中编译不同版本的libqglviewer需要这里设置不同默认版本的qt。想开发win32的选择默认版本为QT_VS2013_32,想开发x64的选择默认版本为QT_VS2013_64)
3.编译libQGLViewer_2.6.3
安装好QT之后,我们下载libQGLViewer_2.6.3,解压后我们用vs2013打开(左上角QT5 -> 打开工程):
右键点击QGLViewer中的生成,或者按下图中的方式生成:
等待,然后看到了成功编译的Debug版本:(注意我们之前设置默认使用的是64位的qt,所以这里得到的是64位的libqglviewer编译结果: QGLViewerd2.lib QGLViewerd2.dll)
选择Release,再编译生成一遍:
同样成功编译并得到了64位的release版的libqglviewer编译结果: QGLViewer2.lib QGLViewer2.dll。
对于32位的,我们只需要更改qt插件的默认配置版本:
确定后重新使用插件打开libQGLViewer.pro,编译生成debug和release即可。完成后可以用不同名字区分开来,方便后续步骤库的选取:
4.Cmake编译g2o源代码
有了Eigen,Qt,libQGLViewer,我们就可以开始编译g2o源代码了,这里也是分32位和64位两个版本。文章一开始已经放出了G2O的下载链接,解压一次命名为win32,在解压一次命名为x64:
(先以32位为例)打开cmake,源码路径和编译路径为下图,提示建立build:
32位的话编译器选择Visual Studio 12 2013:
只需关注eigen,qt,libqglviewer,其他的如csparse等cmake已经帮我们找到了,不需要管。先找到Ungrouped Entries里和G2O里的EIGEN,添加路径(我的为C:/third_party/eigen/include/eigen3,大家的后缀应该一样X:/.../eigen/include/eigen3)。然后对于qt,如果没有改过安装后的qt原文件夹的名字的话,cmake是可以找到的。但是我们这里改成了Qt_32,所以还需要手动添加一下路径(如下图),QT_QMAKE_EXECUTABLE选择qmake.exe文件,Qt5_DIR选择文件夹cmake中的Qt5文件夹:
对于libqglviewer,手动添加include和lib(其中lib为文件,QGLViewerd2.lib是debug版,QGLViewer2.lib是release版):
include选择的是QGLViewer文件夹,而不是里面的文件:
手动添加完后,点击configure,系统会找到剩下的qt相关信息:
再次点击configure确认即可。没有红色后点击generate,即可在build中生成g2o.sln:
接下来再走一边x64的流程。 cmake设置好64位的源代码路径和编译路径,提示创建build文件夹并选择Visual Studio 12 2013 Win64编译器(注意和32位不同):
设置好eigen,qt,libqglviewer的路径:
点击configure:
确认qt的其他信息然后再点一次configure,无红色提示后点击generate:
我们可以看到32位和64位的build文件夹中都出现了g2o.sln:
5.VS2013生成G20
用VS2013打开win32的g2o.sln,然后生成all_build:
等待,然后得到全部成功的结果:
Release下再生成一边:
成功后可以在bin看到生成的lib,dll,exe文件:
VS打开64位文件夹中的g2o.sln然后生成debug版的all_build:
然后64位的release版的all_build:
6.添加环境变量并开始使用
添加环境变量,在path中添加dll的文件夹路径,32位和64位都加上,只开发win32的话不需要添加64位的:
C:\Qt_32\Qt5.5.1\5.5\msvc2013\bin;C:\Qt_64\Qt5.5.1\5.5\msvc2013\bin;C:\g2omaster_x64\bin\Release;C:\g2o-master_x64\bin\Debug; C:\g2o-master_win32\bin\Release; C:\g2o-master_win32\bin\Debug;
到此G2O的编译和环境配置就都完成啦。我在我的slam工程中已经成功使用g2o,其中有一些注意点,将在《关于SLAM的那些事》的第三篇文章中讲到(就是下下篇啦,下篇讲一下视觉SLAM的基本流程和代码)。这里说几个重要的:(1)把C:\g2o-master_win32\build\g2o\config.h拷贝到C:\g2o-master_win32\g2o\下,不然vs中提示找不到config.h (2)把C:\g2o-master_win32\EXTERNAL\csparse\cs.h 和 cs_api.h拷贝到C:\g2o-master_win32\g2o\solvers\csparse\里,然后打开本文件夹下的csparse_helper.h文件,把#include <cs.h>改成#include "cs.h" (3)右键vs工程,属性,C/C++,预处理器 中加上 _WINDOWS(64位的操作相同,注意文件夹)
下面两张图是我跑TUM数据集中的Fr1_XYZ数据集(792帧)的g2o优化结果:第一张没有加保护措施,新的一帧和上一个关键帧之间如果一直没有匹配上(合适的汉明距离,合适的姿态变换),那么接下来很多帧都会丢失,直到重新回到上一个关键帧附近的场景;第二张加了保护措施,连续8帧以上没匹配上,就会把新的一帧加入到关键帧里,同时计算上一个关键帧到这个关键帧的连续姿态变换然后存到图优化的边中。
57个关键帧节点,616条边:
139个关键帧节点,1270条边:
具体的信息接下来的博客中会慢慢讲道。我现在还在学习G2O,未来努力看能不能改进点什么。最后推荐一篇大牛半闲居士的博客,我在上面也学到了很多东西,感谢大家,欢迎交流,共同进步!