当前位置:   article > 正文

使用ORBSLAM2进行kineticV2稠密建图,实时转octomap导航,ROS导航_orbslam2稠密建图octomap

orbslam2稠密建图octomap

 

决定总结最近一个月的工作,这个月在orbslam2的基础上,使用kineticV2完成了稠密点云地图的重建,实现了点云的回环,并使用octomap转换成实时的八叉树地图,导航部分已经有了思路,打算下个月所一个基于octomap的航迹生成能用在视觉的导航上。

一、传感器和依赖包安装

PC性能:Dell xps13   内存16GB   硬盘SSD:500GB     显卡:Intel iris集显

操作系统:ubuntu16.04        ROS:kinetic版本        

依赖库版本:eigen3.1.2  、pcl-1.7、opencv3.2、vtk6.2、octomap1.9、

安装顺序:

1、先安装eigen3.1.2(涉及到很多东西,所以先解决eigen问题)

2、安装pcl1.7、再安装opencv3.2

3、安装kineticV2的libfreenect2、iai_kinect2

4、最后安装octomap

安装eigen3.1.2

  1. cd eigen-eigen-5097c01bcdc4
  2. mkdir build &&cd build
  3. cmake ..
  4. sudo make install


查看eigen版本

pkg-config --modversion eigen3


注:安装eigen不要更改安装路径,这样更换版本时可以自动覆盖原来的路径

2、pcl
本代码使用pcl-1.7版本开发,删除其他版本pcl
locate pcl查看其他版本的pcl安装在哪里,一般存于像/usr/local/share/pcl-1.8 、/usr/local/lib/pkgconfig/等区域,sudo rm -rf 文件路径删除。
例:

sudo rm -rf /usr/local/share/pcl-1.8  /usr/local/lib/pkgconfig/pcl*

locate pcl后如果还有这个文件,打开文件夹的形式打开到那个目录下再看看。有时候多余文件夹或文件已经删了,但是通过命令行locate的还是会有。

  1. cd pcl-pcl-1.7.2 
  2. mkdir build&&cd build
  3. cmake ..
  4. make -j8 (编译大概30分钟)
  5. sudo make install 


编译有问题的话百度下,基本上都是eigen或者各种依赖库版本不对导致的。

3、下载安装libfreenect

安装方式参考https://github.com/OpenKinect/libfreenect2

  1. git clone https://github.com/OpenKinect/libfreenect2.git
  2. cd libfreenect2
  3. sudo apt-get install build-essential cmake pkg-config
  4. sudo apt-get install libusb-1.0-0-dev
  5. sudo apt-get install libturbojpeg libjpeg-turbo8-dev
  6. sudo apt-get install libglfw3-dev
  7. sudo apt-get install libopenni2-dev
  8. cd ..
  9. mkdir build && cd build
  10. cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/freenect2
  11. make
  12. make install

设定udev rules:

libfreenect2目录下执行

sudo cp ../platform/linux/udev/90-kinect2.rules /etc/udev/rules.d/

重新插拔设备

运行Demo程序: libfreenect2目录下执行    ./build/bin/Protonect, 不出意外, 应该能够看到如下效果:

注意:这里要分别测测cpu、opengl、opencl模型下的情况

 

  1. ./build/bin/Protonect cpu
  2. ./build/bin/Protonect gl
  3. ./build/bin/Protonect cl

 

尤其是使用opengl和opencl跑的,NVIDIA和Intel需要先安装NVIDIA的cuda后再执行,opencl执行不过关会影响后面iai_kinect2安装后执行roslaunch kinect2_bridge kinect2_bridge.launch的效果,这里我们先测一下,只要有图像就行,如果gl、或者cl执行不出来问题先保留,在iai_kinect2安装后再给出对应解决方案。

4、iai_kinect2

利用命令行从Github上面下载工程源码到工作空间内src文件夹内:

  1. cd ~/catkin_ws/src/
  2. git clone https://github.com/code-iai/iai_kinect2.git
  3. cd iai_kinect2
  4. rosdep install -r --from-paths .
  5. cd ~/catkin_ws
  6. catkin_make -DCMAKE_BUILD_TYPE="Release"

安装iai-kinect2操作这一步"rosdep install  -r --from-paths 出现错误
ERROR: the following packages/stacks could not have their rosdep keys resolved
to system dependencies:
kinect2_viewer: Cannot locate rosdep definition for [kinect2_bridge]
kinect2_calibration: Cannot locate rosdep definition for [kinect2_bridge]
kinect2_bridge: Cannot locate rosdep definition for [kinect2_registration]
Continuing to install resolvable dependencies...
解决办法:命令改写为:

  1. rosdep install --from-paths ~/catkin_ws/src/iai_kinect2 --ignore-src -r

执行下面命令查看能否正常执行kineticV2

roslaunch kinect2_bridge kinect2_bridge.launch

如果安装正常是可以执行的,

.......

[ INFO] [1565591147.113376730]: [DepthRegistration::New] Using CPU registration method!
[ INFO] [1565591147.113685492]: [DepthRegistration::New] Using CPU registration method!
[ INFO] [1565591147.192329239]: [Kinect2Bridge::main] waiting for clients to connect
这里最后一行显示等待客户端连接,这个是正常的,因为会产生大量的计算量,因此默认不会自动打开显示窗口,

执行rostopic list明显看到是有话题的,当订阅相关话题时才会有数据。执行:

rosrun rviz rviz

左下角add —— image 在Image Topic中选/kinect2/qhd/image_color_rect  ,可以看到图像,则kinect2可以正常使用了

5、出错排雷

好,关于kineticV2该安装的都安装完了,接下来我讲讲我遇到过的问题,供各位朋友们参考

a、其实我遇到的核心问题就是双显卡状态下,cl不能执行的问题。一开始在我的台式机(双显卡)上执行./build/bin/Protonect cl,报错,找不到opencl设备;执行roslaunch kinect2_bridge kinect2_bridge.launch。报错如下:

[ INFO] [1565590436.239968384]: [DepthRegistration::New] Using OpenCL registration method!
[ INFO] [1565590436.240130258]: [DepthRegistration::New] Using OpenCL registration method!
beignet-opencl-icd: no supported GPU found, this is probably the wrong opencl-icd package for this hardware
(If you have multiple ICDs installed and OpenCL works, you can ignore this message)
[ INFO] [1565590436.245914876]: [DepthRegistrationOpenCL::init] devices:
[ERROR] [1565590436.245966385]: [DepthRegistrationOpenCL::init] could not find any suitable device
[Info] [Freenect2DeviceImpl] closing...
[Info] [Freenect2DeviceImpl] releasing usb interfaces...
[Info] [Freenect2DeviceImpl] deallocating usb transfer pools...
[Info] [Freenect2DeviceImpl] closing usb device...
[Info] [Freenect2DeviceImpl] closed
[ERROR] [1565590436.247492556]: [Kinect2Bridge::start] Initialization failed!

......
[Error] [OpenCLDepthPacketProcessorImpl] OpenCLDepthPacketProcessor is not initialized!
[Error] [OpenCLDepthPacketProcessorImpl] OpenCLDepthPacketProcessor is not initialized!
[Error] [OpenCLDepthPacketProcessorImpl] OpenCLDepthPacketProcessor is not initialized!
[Info] [Freenect2DeviceImpl] submitting rgb transfers...
[Info] [Freenect2DeviceImpl] submitting depth transfers...
[Error] [DepthPacketStreamParser] Packet buffer is NULL
[Error] [DepthPacketStreamParser] Packet buffer is NULL

查看错误信息我们可以得知问题出在opencl上,找不到opencl设备

解决方案:

a、查看https://github.com/OpenKinect/libfreenect2里关于双显卡的安装依赖包,下载nvidia对应显卡的cuda,两个显卡都安装后,重新编译,再执行其他操作。在xps13的笔记本上只有一个显卡,所以一遍通过。

b、如果不安装opencl,则可以通过opengl+cpu的形式执行,opengl用来计算深度图(depth),cpu用来计算(color)的方式,解决。

修改iai_kinect2/kinect2_bridge/launch下kinect2_bridge.launch
将  
<arg name="depth_method"      default="default"/>
<arg name="reg_method"        default="default"/>
修改为
<arg name="depth_method"      default="opengl"/>
<arg name="reg_method"        default="cpu"/>

再次执行roslaunch kinect2_bridge kinect2_bridge.launch,报错

[Kinect2Bridge::initRegistration] CPU registration is not available! ".
参考解决方案:https://github.com/code-iai/iai_kinect2/issues/447
这里找不到cpu是因为eigen找不到的原因

locate FindEigen3.cmake

locate找到FindEigen3.cmake复制到iai_kinect2/kinect2_registration/cmake下,重新catkin_make整个iai_kinect2工程可解决问题。

6、安装octomap1.9
源码下载git clone https://github.com/OctoMap/octomap.git
cd octomap
mkdir build&&cd build
cmake ..
make
sudo make install

传感器安装部分结束。安装参考博客https://blog.csdn.net/wuguangbin1230/article/details/77184032

 

二、基于ORBSLAM2的pcl-1.7点云拼接与三维稠密点云重建

先进行个稠密点云的三维重建,感谢高博做出的工作!https://github.com/gaoxiang12/ORBSLAM2_with_pointcloud_map

在高博基础上,另一位大佬给稠密地图加了回环https://github.com/tiantiandabaojian/ORB-SLAM2_RGBD_DENSE_MAP.git

我的工作是将kineticV2相机的稠密点云实时转换成octomap,并在rviz里进行展示。

原理:用单目、双目、RGBD都可以进行稠密地图的建立,建立全局地图是我们实现导航的第一步,通过相机图像将像素转换为点云(pointcloud)数据,进而进行拼接,在此基础上如果要恢复物体外观轮廓,就需要使用三角网格(mesh)、面片(surfel)进行建图,这样的生成的pcd点云地图往往很大,跑tum生成的数据集都可达到5、600MB的大小,用于导航的话非常不利于我们设备进行导航地图的导入,所以亦可以通过体素(voxel)占据网格地图(Occupancy Map)。

点云包含xyz和rgb信息

外点滤波器以及降采样滤波器。

 

数据集实现效果:

 

先抛出代码,后面解释

pointcloudmapping.c文件

  1. /*
  2. * <one line to give the program's name and a brief idea of what it does.>
  3. * Copyright (C) 2016 <copyright holder> <email>
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #include "pointcloudmapping.h"
  20. #include <KeyFrame.h>
  21. #include <opencv2/highgui/highgui.hpp>
  22. #include <pcl/visualization/cloud_viewer.h>
  23. #include <pcl/filters/statistical_outlier_removal.h>
  24. #include "Converter.h"
  25. #include "PointCloude.h"
  26. #include "System.h"
  27. int currentloopcount = 0;
  28. /*
  29. *
  30. * @param resolution_ :体素大小分辨率,分辨率越小,单个体素越小
  31. * @param meank_ : meank_ 为在进行统计时考虑查询邻近点个数
  32. * @param thresh_:设置距离阈值,其公式是 mean + global stddev_mult * global stddev,即mean+1.0*stddev
  33. * @return :无
  34. */
  35. PointCloudMapping::PointCloudMapping(double resolution_,double meank_,double thresh_)
  36. {
  37. this->resolution = resolution_;//分辨率
  38. this->meank = thresh_;
  39. this->thresh = thresh_;
  40. statistical_filter.setMeanK(meank);//统计估计滤波参数
  41. statistical_filter.setStddevMulThresh(thresh);
  42. voxel.setLeafSize( resolution, resolution, resolution);//设置每个体素子叶分辨率
  43. globalMap = boost::make_shared< PointCloud >( );
  44. viewerThread = make_shared<thread>( bind(&PointCloudMapping::viewer, this ) );
  45. }
  46. /*
  47. * void PointCloudMapping::shutdown()
  48. * \brief 关闭建图线程
  49. */
  50. void PointCloudMapping::shutdown()
  51. {
  52. {
  53. unique_lock<mutex> lck(shutDownMutex);
  54. shutDownFlag = true;
  55. keyFrameUpdated.notify_one();
  56. }
  57. //等待PointCloudMapping_viewer 本线程执行结束再执行系统主线程
  58. viewerThread->join();
  59. }
  60. //插入关键帧
  61. /*
  62. *
  63. * @param kf 关键帧
  64. * @param color 关键帧彩色图
  65. * @param depth 关键帧深度图
  66. * @param idk 第idk个关键帧
  67. * @param vpKFs 获取全部关键帧
  68. * @function 在点云地图里插入关键帧
  69. */
  70. void PointCloudMapping::insertKeyFrame(KeyFrame* kf, cv::Mat& color, cv::Mat& depth,int idk,vector<KeyFrame*> vpKFs)
  71. {
  72. cout<<"receive a keyframe, id = "<<idk<<" 第"<<kf->mnId<<"个"<<endl;
  73. //cout<<"vpKFs数量"<<vpKFs.size()<<endl;
  74. unique_lock<mutex> lck(keyframeMutex);
  75. keyframes.push_back( kf );
  76. currentvpKFs = vpKFs;
  77. //colorImgs.push_back( color.clone() );
  78. //depthImgs.push_back( depth.clone() );
  79. PointCloude pointcloude;
  80. pointcloude.pcID = idk;
  81. pointcloude.T = ORB_SLAM2::Converter::toSE3Quat( kf->GetPose() );//获取关键帧位姿
  82. pointcloude.pcE = generatePointCloud(kf,color,depth);//迭代关键帧点云
  83. pointcloud.push_back(pointcloude);
  84. keyFrameUpdated.notify_one();//通知线程开锁
  85. }
  86. /**
  87. *
  88. * @param kf 关键帧
  89. * @param color 彩色图
  90. * @param depth 深度图
  91. * @return 关键帧点云
  92. */
  93. pcl::PointCloud< PointCloudMapping::PointT >::Ptr PointCloudMapping::generatePointCloud(KeyFrame* kf, cv::Mat& color, cv::Mat& depth)//,Eigen::Isometry3d T
  94. {
  95. //新建一个点云// point cloud is null ptr
  96. PointCloud::Ptr tmp( new PointCloud() );
  97. //对点云进行
  98. for ( int m=0; m<depth.rows; m+=2 )
  99. {
  100. for ( int n=0; n<depth.cols; n+=2 )
  101. {
  102. float d = depth.ptr<float>(m)[n];//获取(m,n)处的深度值
  103. if (d < 0.01 || d>5)//滤除设备可靠深度范围之外点
  104. continue;
  105. PointT p;
  106. //相机模型,只计算关键帧的点云
  107. //坐标系与pcl坐标系相反,所以可以p.z=-d
  108. p.z = d;
  109. p.x = ( n - kf->cx) * p.z / kf->fx;
  110. p.y = ( m - kf->cy) * p.z / kf->fy;
  111. //彩色图计算点云颜色
  112. p.b = color.ptr<uchar>(m)[n*3];
  113. p.g = color.ptr<uchar>(m)[n*3+1];
  114. p.r = color.ptr<uchar>(m)[n*3+2];
  115. tmp->points.push_back(p);
  116. }
  117. }
  118. //cout<<"generate point cloud for kf "<<kf->mnId<<", size="<<cloud->points.size()<<endl;
  119. return tmp;
  120. }
  121. /*
  122. * @brief 显示点云线程
  123. */
  124. void PointCloudMapping::viewer()
  125. {
  126. //创建显示点云窗口
  127. pcl::visualization::CloudViewer viewer("viewer");
  128. while(1)
  129. {
  130. {
  131. unique_lock<mutex> lck_shutdown( shutDownMutex );
  132. if (shutDownFlag)
  133. {
  134. break;
  135. }
  136. }
  137. {
  138. unique_lock<mutex> lck_keyframeUpdated( keyFrameUpdateMutex );
  139. keyFrameUpdated.wait( lck_keyframeUpdated );
  140. }
  141. // keyframe is updated
  142. size_t N=0;
  143. {
  144. unique_lock<mutex> lck( keyframeMutex );
  145. N = keyframes.size();
  146. }
  147. if(loopbusy || bStop)
  148. {
  149. //cout<<"loopbusy || bStop"<<endl;
  150. continue;
  151. }
  152. //cout<<lastKeyframeSize<<" "<<N<<endl;
  153. if(lastKeyframeSize == N)
  154. cloudbusy = false;
  155. //cout<<"待处理点云个数 = "<<N<<endl;
  156. cloudbusy = true;
  157. for ( size_t i=lastKeyframeSize; i<N ; i++ )
  158. {
  159. PointCloud::Ptr p (new PointCloud);
  160. //将点云数据转换成ascii码形式存储在pcd文件中
  161. //1、源点云 2、转变后的点云 3、位姿变换矩阵
  162. pcl::transformPointCloud( *(pointcloud[i].pcE), *p, pointcloud[i].T.inverse().matrix());
  163. // 转换后的点云叠加存储在globalMap中
  164. *globalMap += *p;
  165. }
  166. // depth filter and statistical removal
  167. //这里的滤波只是显示上的滤波
  168. PointCloud::Ptr tmp1 ( new PointCloud );
  169. statistical_filter.setInputCloud(globalMap); //对globalMap进行统计学去噪
  170. statistical_filter.filter( *tmp1 ); // 执行去噪计算并保存点到 tmp1
  171. //体素滤波器voxel filter进行降采样
  172. PointCloud::Ptr tmp(new PointCloud());
  173. voxel.setInputCloud( tmp1 );
  174. voxel.filter( *globalMap );
  175. //globalMap->swap( *tmp );
  176. viewer.showCloud( globalMap );
  177. cout<<"show global map, size="<<N<<" "<<globalMap->points.size()<<endl;
  178. lastKeyframeSize = N;
  179. cloudbusy = false;
  180. }
  181. }
  182. /*
  183. * 保存pcd地图
  184. */
  185. void PointCloudMapping::save()
  186. {
  187. pcl::io::savePCDFile( "/home/linker/catkin_make/src/MYNT-EYE-ORB-SLAM2-Sample/result.pcd", *globalMap );
  188. cout<<"globalMap save finished"<<endl;
  189. }
  190. /*
  191. * 更新点云
  192. */
  193. void PointCloudMapping::updatecloud()
  194. {
  195. if(!cloudbusy)
  196. {
  197. loopbusy = true;
  198. cout<<"startloopmappoint"<<endl;
  199. PointCloud::Ptr tmp1(new PointCloud);
  200. for (int i=0;i<currentvpKFs.size();i++)
  201. {
  202. for (int j=0;j<pointcloud.size();j++)
  203. {
  204. if(pointcloud[j].pcID==currentvpKFs[i]->mnFrameId)
  205. {
  206. Eigen::Isometry3d T = ORB_SLAM2::Converter::toSE3Quat(currentvpKFs[i]->GetPose() );
  207. PointCloud::Ptr cloud(new PointCloud);
  208. pcl::transformPointCloud( *pointcloud[j].pcE, *cloud, T.inverse().matrix());
  209. *tmp1 +=*cloud;
  210. continue;
  211. }
  212. }
  213. }
  214. cout<<"finishloopmap"<<endl;
  215. PointCloud::Ptr tmp2(new PointCloud());
  216. voxel.setInputCloud( tmp1 );
  217. voxel.filter( *tmp2 );
  218. globalMap->swap( *tmp2 );
  219. loopbusy = false;
  220. loopcount++;
  221. }
  222. }
  223. //获取全局点云地图点,智能指针,return 回来
  224. pcl::PointCloud<PointCloudMapping::PointT>::Ptr PointCloudMapping::getGlobalMap() {
  225. return this->globalMap;
  226. }

pointcloudmapping.h

  1. /*
  2. * <one line to give the program's name and a brief idea of what it does.>
  3. * Copyright (C) 2016 <copyright holder> <email>
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #ifndef POINTCLOUDMAPPING_H
  20. #define POINTCLOUDMAPPING_H
  21. #include "System.h"
  22. #include "PointCloude.h"
  23. #include <pcl/common/transforms.h>
  24. #include <pcl/point_types.h>
  25. #include <pcl/filters/voxel_grid.h>
  26. #include <condition_variable>
  27. #include <pcl/io/pcd_io.h>
  28. #include <pcl/filters/statistical_outlier_removal.h>
  29. using namespace std;
  30. using namespace ORB_SLAM2;
  31. class PointCloudMapping
  32. {
  33. public:
  34. //定义点云类型
  35. typedef pcl::PointXYZRGBA PointT;
  36. typedef pcl::PointCloud<PointT> PointCloud;
  37. PointCloudMapping( double resolution_,double meank_,double thresh_ );
  38. void save();
  39. // 插入一个keyframe,会更新一次地图
  40. void insertKeyFrame( KeyFrame* kf, cv::Mat& color, cv::Mat& depth,int idk,vector<KeyFrame*> vpKFs );
  41. void shutdown();
  42. void viewer();
  43. void inserttu( cv::Mat& color, cv::Mat& depth,int idk);
  44. int loopcount = 0;
  45. vector<KeyFrame*> currentvpKFs;
  46. bool cloudbusy;
  47. bool loopbusy;
  48. void updatecloud();
  49. bool bStop = false;
  50. PointCloud::Ptr getGlobalMap();
  51. protected:
  52. PointCloud::Ptr globalMap;
  53. PointCloud::Ptr generatePointCloud(KeyFrame* kf, cv::Mat& color, cv::Mat& depth);
  54. //PointCloud::Ptr globalMap;
  55. shared_ptr<thread> viewerThread;
  56. bool shutDownFlag =false;
  57. mutex shutDownMutex;
  58. condition_variable keyFrameUpdated;
  59. mutex keyFrameUpdateMutex;
  60. vector<PointCloude> pointcloud;
  61. // data to generate point clouds
  62. vector<KeyFrame*> keyframes;
  63. vector<cv::Mat> colorImgs;
  64. vector<cv::Mat> depthImgs;
  65. vector<cv::Mat> colorImgks;
  66. vector<cv::Mat> depthImgks;
  67. vector<int> ids;
  68. mutex keyframeMutex;
  69. uint16_t lastKeyframeSize =0;
  70. double resolution = 0.04;
  71. double meank = 50;
  72. double thresh = 1;
  73. pcl::VoxelGrid<PointT> voxel;
  74. pcl::StatisticalOutlierRemoval<PointT> statistical_filter;
  75. };
  76. #endif // POINTCLOUDMAPPING_H

system.cc

  1. void System::Shutdown()
  2. {
  3. mpLocalMapper->RequestFinish();
  4. mpLoopCloser->RequestFinish();
  5. mpPointCloudMapping->shutdown();
  6. if(mpViewer)
  7. {
  8. mpViewer->RequestFinish();
  9. while(!mpViewer->isFinished())
  10. usleep(5000);
  11. }
  12. // Wait until all thread have effectively stopped
  13. while(!mpLocalMapper->isFinished() || !mpLoopCloser->isFinished() || mpLoopCloser->isRunningGBA())
  14. {
  15. usleep(5000);
  16. }
  17. if(mpViewer)
  18. pangolin::BindToContext("ORB-SLAM2: Map Viewer");
  19. }
  1. void System::save()
  2. {
  3. mpPointCloudMapping->save();
  4. }
  5. pcl::PointCloud<PointCloudMapping::PointT>::Ptr System::getGlobalMap() {
  6. return mpPointCloudMapping->getGlobalMap();
  7. }
  8. int System::getloopcount()
  9. {
  10. return mpLoopCloser->loopcount;
  11. }
  12. }

track.cc中void Tracking::CreateNewKeyFrame()函数添加 

  1. // insert Key Frame into point cloud viewer
  2. vector<KeyFrame*> vpKFs = mpMap->GetAllKeyFrames();
  3. mpPointCloudMapping->insertKeyFrame( pKF, this->mImRGB, this->mImDepth ,idk,vpKFs);

LoopClousing.cc的void LoopClosing::RunGlobalBundleAdjustment(unsigned long nLoopKF)添加代码

  1. //稠密建图
  2. loopcount++;
  3. while(loopcount!=mpPointCloudMapping->loopcount)
  4. mpPointCloudMapping->updatecloud();
  5. cout<<"mpPointCloudMapping->loopcount="<<mpPointCloudMapping->loopcount<<endl;

接下来我将生成的稠密点云通过ros_octomap映射到ros话题中,octomap原理高博在书中已经讲的很详细了。

在ros里进行展示

ros_rgbd.cc

  1. int main(int argc, char **argv)
  2. {
  3. ros::init(argc, argv, "RGBD");
  4. ros::start();
  5. if(argc != 3)
  6. {
  7. cerr << endl << "Usage: rosrun ORB_SLAM2 RGBD path_to_vocabulary path_to_settings" << endl;
  8. ros::shutdown();
  9. return 1;
  10. }
  11. // Create SLAM system. It initializes all system threads and gets ready to process frames.
  12. ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::RGBD,true);
  13. ImageGrabber igb(&SLAM);
  14. ros::NodeHandle nh;
  15. //原代码
  16. // message_filters::Subscriber<sensor_msgs::Image> rgb_sub(nh, "/camera/rgb/image_raw", 1);
  17. // message_filters::Subscriber<sensor_msgs::Image> depth_sub(nh, "camera/depth_registered/image_raw", 1);
  18. //修改为kinect2
  19. message_filters::Subscriber<sensor_msgs::Image> rgb_sub(nh, "/kinect2/qhd/image_color", 1);
  20. message_filters::Subscriber<sensor_msgs::Image> depth_sub(nh, "/kinect2/qhd/image_depth_rect", 1);
  21. typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image> sync_pol;
  22. message_filters::Synchronizer<sync_pol> sync(sync_pol(10), rgb_sub,depth_sub);
  23. sync.registerCallback(boost::bind(&ImageGrabber::GrabRGBD,&igb,_1,_2));
  24. //TODO OCTOMAP添加
  25. pcl::PointCloud<pcl::PointXYZRGBA>::Ptr global_map(new pcl::PointCloud<pcl::PointXYZRGBA>);
  26. global_map = SLAM.mpPointCloudMapping->getGlobalMap();
  27. pcl::PointCloud<pcl::PointXYZRGB>::Ptr global_map_copy(new pcl::PointCloud<pcl::PointXYZRGB>);
  28. //数据格式转换
  29. cout<<"-----------------------------------------------------------"<<endl;
  30. cout <<"ros is running "<<endl;
  31. while (ros::ok())
  32. {
  33. pcl::copyPointCloud(*global_map, *global_map_copy);
  34. ros::Publisher pcl_pub = nh.advertise<sensor_msgs::PointCloud2> ("/orbslam2_with_kinect2/output", 10);
  35. sensor_msgs::PointCloud2 output;
  36. pcl::toROSMsg(*global_map_copy,output);// 转换成ROS下的数据类型 最终通过topic发布
  37. output.header.stamp=ros::Time::now();
  38. output.header.frame_id ="camera_rgb_frame";
  39. //output.header.frame_id ="map";
  40. ros::Rate loop_rate(10);
  41. pcl_pub.publish(output);
  42. ros::spinOnce();
  43. loop_rate.sleep();
  44. }
  45. //TODO 结束
  46. //ros::spin();
  47. SLAM.save();
  48. // Stop all threads
  49. SLAM.Shutdown();
  50. // Save camera trajectory
  51. SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");
  52. ros::shutdown();
  53. return 0;
  54. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/386651
推荐阅读
相关标签
  

闽ICP备14008679号