RGBD_SLAM视觉里程计
[TOC]
小小的说明
学习笔记
学习地址:https://www.cnblogs.com/gaoxiang12/p/4719156.html
这是第一次写关于SLAM的博客。在学习完高翔博士的SLAM14讲的前八章之后(其实还差几页没看完,不过还是做出来了这个视觉里程计的嘛(虽然是很简陋的那种),嘻嘻嘻。),看见群里老哥推荐高翔博士的书和高博士的“一起做RGBD_SLAM”博客一起看,于是我就利用晚上10点自习回来之后到睡觉之间的时间以及早上6:10起床然后到上午上课之间的时间进行博客的学习。
经过两天半的学习与编码,完成了这个视觉里程计,当然这个视觉里程计还是非常粗糙的,后续还需要对其进行一些参数优化,然后还有后端一些处理的学习。
另外,高翔博士的github上的代码都是正确的,只是由于各种环境配置问题或者是各个库的版本问题,并不一定能直接在各位的电脑上跑起来,可以参照我代码进行一些功能的修改,但是由于我的代码结构和高翔博士的有些地方不太一样(个人认为高翔博士的代码更加容易维护,封装程度较高,对于这个百行级别的Demo甚至写了一个读取配置文件的类,而我这个虽然各个函数都进行了封装,但是有些地方写的比较随意。。。),所以还请各位使用时要仔细对照一下。
我的学习环境为:
Ubuntu 16.04
OpenCV 3.4.5
GitHUb:https://github.com/RasertingL/My_RGBD_SLAM
掉进去的坑
- slamBase.cpp中的cvMat2Eigen函数里的cv::cv2eigen()报错
为了将旋转向量revc转化为变换矩阵有如下步骤:
- 使用罗德里格变换(Rodrigues)将cv::Mat类型的旋转向量转化为旋转矩阵
- 将cv::Mat类型的旋转矩阵转化为Eigen::Matrix3d类型的旋转矩阵
- 然后将旋转矩阵与平移向量转化为变换矩阵
也就是第二步:将cv::Mat类型的旋转矩阵转化为Eigen::Matrix3d类型的旋转矩阵,使用了一个opencv中的函数cv::cv2eigen(cv::Mat, Eigen::Matrix),这个函数可把我弄惨了,一调用,这个函数就报说Eigen未定义,但是这个函数里的Eigen应该是opencv里自带的啊,怎么可能会出错,并且我外面使用的Eigen也没报错额。然后调了半天,最后将头文件顺序按照高博士github里的顺序改了下,然后把CmakeLists.txt里Eigen的引入语句去掉了,最后,竟然,竟然编译通过了。。。真的很玄学。
终极解决方案:后面高博给出了个解决方案,不使用这个cv::cv2eigen()函数了,手写一个同样效果的代码:
for ( int i=0; i<3; i++ )
for ( int j=0; j<3; j++ )
r(i,j) = R.at<double>(i,j);
- visualOdometry.cpp中最后关于pcl的显示以及滤波报错问题
在调完各种bug后,眼看着cmake .. 成功,然后make达到了100%,到达了最后的链接阶段,想着我好想没在链接的地方掉过大链子,准备长舒一口气,可是,竟然,竟然,最后的链接报错了,但是并不是报什么库不存在什么的,而是显示pcl::visualization::CloudViewer的CloudViewer未定义,我滴妈呀,啥就未定义呀,当时喝水都差点喷出来了,这都pcl里封装的额,咋就未定义了。没办法,查了查这个报错,然后找到了一个老哥的博客(我也不知道怎么判断出来是老哥的,反正感觉就是),他说,他也遇到了这个问题,然后他把自己的代码用高博的代码替代了,然后就成了。。。
emmmmmm,原来debug的最佳方式就是让别人的代码替代自己的代码(没有diss老哥的意思,其实他的这种特殊debug方式给了我启发),但是也不行啊,我这代码结构和高博的不太一样,我这一换,,,全都得换啊,怕不是和直接github下一份没区别。。。
但是想了想,我先确定下关于pcl::visualization::CloudViewer这种写法没问题吧,于是我把高博的github上的代码拿来了(哎哟,真香,哎呦),然后运行,根据报错,把里面的由于版本原因的问题改了下,然后就跑起来了。在确定了这样的写法没问题之后,我还是回到了自己的代码,由于是最后的链接阶段的报错,我感觉还是CMakeLists.txt的问题,于是我对着我自己的CMakeLists.txt和高博的CMakeLists.txt来找不同了,,,这一找,果然有了,在导入pcl库的时候,由于要是用visualization和滤波,所以CMakeLists.txt里应该对应写上对这俩的导入,但是呢,由于太笨,忘了写。。。
emmm不过,解决这一个Bug的同时,也解决了下面的的滤波未定义报错的情况(好吧,这个不说大家也能知道,emmmm对不起,我多嘴了)。
高博的代码改法
对了,这里一定有读者会说,我不想自己重新打一遍,我就想调通高博的代码,该怎么调,其实,高博的代码目前因为版本问题,就两个地方需要改:
-
slamBase.cpp中computeKeyPointsAndDesp()函数中的。keypoints检测器和descripter计算器的创建问题,可能由于OpenCV版本更新导致的feature2d类里面已经没有create()函数了,所以报错找不到相应函数。改成auto detector = cv::ORB::create();这种ORB的就好了。
整个函数改动如下:
void computeKeyPointsAndDesp(FRAME &frame) { /* cv::Ptr<cv::FeatureDetector> _detector = cv::ORB::create(); cv::Ptr<cv::DescriptorExtractor> _descriptor = cv::ORB::create(); _detector->detect(frame.rgb, frame.kp); _descriptor->compute(frame.rgb, frame.kp, frame.desp); 改成: */ auto detector = cv::ORB::create(); detector->detectAndCompute(frame.rgb, cv::noArray(), frame.kp, frame.desp); cout<<"keypoints : "<<frame.kp.size()<<endl; return; }
-
另外也是因为OpenCV更新导致的solvePnPRansac()增加了一个置信区间参数,值为0-1。设置为默认值0.99就好了。
cv::solvePnPRansac(pts_obj, pts_img, cameraMatrix, cv::Mat(), rvec, tvec, false, 100, 1.0, 0.99, inliers);
然后就可以开始愉悦得跑结果辣!!!
One more thing
现在已经是凌晨0:37了,明天,不对,是今天还要早起第一节课,主要是我想一鼓作气一定要写完这SLAM的第一篇博客。作为一个SLAM初学者,和一个接触C已经快三年的人,通过这次代码练习,我发现,由于各种库的使用(从代码中可以看到,pnp都不用自己求,直接opencv帮你搞定,还是是带RANSAC的那种。。。想想就很一颗赛特好么。。。),SLAM中的理论数学推导相比之下显得难度大得多。但是可以明显感觉到,在学习了SLAM14讲之后再做这个,有一种理论与实践结合的赶脚(虽然这个结合在大佬看来肯定很Low)。。。。。。
emmmmmmmmmm,理论学习很重要,共勉。