BundleAdjustment函数

1、理论部分(待更新)

2、代码详解

//BA优化
// BundleAdjustment( vpKFs //关键帧,vpMP //地图点,nIterations //迭代次数,pbStopFlag //停止标志, nLoopKF   //回环帧数量, bRobust   //是否进行鲁棒核函数);
void Optimizer::BundleAdjustment(const vector<KeyFrame *> &vpKFs, const vector<MapPoint *> &vpMP,int nIterations, bool* pbStopFlag, const unsigned long nLoopKF, const bool bRobust)
{//判断每个地图点是否更新vector<bool> vbNotIncludedMP;vbNotIncludedMP.resize(vpMP.size());//构造优化器g2o::SparseOptimizer optimizer;//线性求解器 Hx = bg2o::BlockSolver_6_3::LinearSolverType * linearSolver;//分配空间linearSolver = new g2o::LinearSolverEigen<g2o::BlockSolver_6_3::PoseMatrixType>();g2o::BlockSolver_6_3 * solver_ptr = new g2o::BlockSolver_6_3(linearSolver);//LM算法进行求解g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);optimizer.setAlgorithm(solver);//用于停止求解if(pbStopFlag)optimizer.setForceStopFlag(pbStopFlag);long unsigned int maxKFid = 0;// Set KeyFrame vertices//建立关键帧的顶点//遍历所有关键帧for(size_t i=0; i<vpKFs.size(); i++){//提取每一个关键帧KeyFrame* pKF = vpKFs[i];//若为ie坏帧剔除if(pKF->isBad())continue;//定义顶点从 李代数的形式g2o::VertexSE3Expmap * vSE3 = new g2o::VertexSE3Expmap();//导入要估计的数据(位姿)vSE3->setEstimate(Converter::toSE3Quat(pKF->GetPose()));//导入索引vSE3->setId(pKF->mnId);//固定第一帧的位置vSE3->setFixed(pKF->mnId==0);//添加顶点optimizer.addVertex(vSE3);//若索引最大则替换当前最大索引  if(pKF->mnId>maxKFid)maxKFid=pKF->mnId;}//鲁棒核函数const float thHuber2D = sqrt(5.99);const float thHuber3D = sqrt(7.815);// Set MapPoint vertices//建立地图点的顶点 for(size_t i=0; i<vpMP.size(); i++){MapPoint* pMP = vpMP[i];if(pMP->isBad())continue;g2o::VertexSBAPointXYZ* vPoint = new g2o::VertexSBAPointXYZ();vPoint->setEstimate(Converter::toVector3d(pMP->GetWorldPos()));//索引位于位姿之后const int id = pMP->mnId+maxKFid+1;vPoint->setId(id);//边缘化(加速求解)vPoint->setMarginalized(true);optimizer.addVertex(vPoint);//获取观测值const map<KeyFrame*,size_t> observations = pMP->GetObservations();int nEdges = 0;//SET EDGES//创建边//遍历所有观测值for(map<KeyFrame*,size_t>::const_iterator mit=observations.begin(); mit!=observations.end(); mit++){//获取观测的关键帧KeyFrame* pKF = mit->first;//如果该帧为坏帧,或者索引大于最大索引,那便跳过if(pKF->isBad() || pKF->mnId>maxKFid)continue;nEdges++;//获取关键帧中的关键点const cv::KeyPoint &kpUn = pKF->mvKeysUn[mit->second];// 单目或RGBD相机if(pKF->mvuRight[mit->second]<0){//观测像素点Eigen::Matrix<double,2,1> obs;obs << kpUn.pt.x, kpUn.pt.y;g2o::EdgeSE3ProjectXYZ* e = new g2o::EdgeSE3ProjectXYZ();//优化的顶点0 地图点e->setVertex(0, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(id)));//优化的顶点1 位姿e->setVertex(1, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(pKF->mnId)));//导入观测e->setMeasurement(obs);//定义信息矩阵const float &invSigma2 = pKF->mvInvLevelSigma2[kpUn.octave];e->setInformation(Eigen::Matrix2d::Identity()*invSigma2);//鲁棒核函数if(bRobust){g2o::RobustKernelHuber* rk = new g2o::RobustKernelHuber;e->setRobustKernel(rk);rk->setDelta(thHuber2D);//结构里有结构}//导入相机、内参e->fx = pKF->fx;e->fy = pKF->fy;e->cx = pKF->cx;e->cy = pKF->cy;//添加边optimizer.addEdge(e);}else //双目{Eigen::Matrix<double,3,1> obs;const float kp_ur = pKF->mvuRight[mit->second];obs << kpUn.pt.x, kpUn.pt.y, kp_ur;g2o::EdgeStereoSE3ProjectXYZ* e = new g2o::EdgeStereoSE3ProjectXYZ();e->setVertex(0, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(id)));e->setVertex(1, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(pKF->mnId)));e->setMeasurement(obs);const float &invSigma2 = pKF->mvInvLevelSigma2[kpUn.octave];Eigen::Matrix3d Info = Eigen::Matrix3d::Identity()*invSigma2;e->setInformation(Info);if(bRobust){g2o::RobustKernelHuber* rk = new g2o::RobustKernelHuber;e->setRobustKernel(rk);rk->setDelta(thHuber3D);}e->fx = pKF->fx;e->fy = pKF->fy;e->cx = pKF->cx;e->cy = pKF->cy;e->bf = pKF->mbf;optimizer.addEdge(e);}}//如果边的数量为0,则清除顶点if(nEdges==0){optimizer.removeVertex(vPoint);vbNotIncludedMP[i]=true;}else{vbNotIncludedMP[i]=false;}}//添加边结束// Optimize!//开始进行优化optimizer.initializeOptimization();optimizer.optimize(nIterations);// Recover optimized data//得到优化后的数据//Keyframes 关键帧//遍历每一个关键帧并提取优化后的位姿for(size_t i=0; i<vpKFs.size(); i++){KeyFrame* pKF = vpKFs[i];if(pKF->isBad())continue;//提取估计好的位姿g2o::VertexSE3Expmap* vSE3 = static_cast<g2o::VertexSE3Expmap*>(optimizer.vertex(pKF->mnId));g2o::SE3Quat SE3quat = vSE3->estimate();//不发生回环if(nLoopKF==0){//无回环就默认当前位姿pKF->SetPose(Converter::toCvMat(SE3quat));}else//若出现回环要提取估计值进行回环检测在更新位姿{pKF->mTcwGBA.create(4,4,CV_32F);Converter::toCvMat(SE3quat).copyTo(pKF->mTcwGBA);pKF->mnBAGlobalForKF = nLoopKF;}}//Keyframes 关键帧//Points 地图点特征点//遍历地图点for(size_t i=0; i<vpMP.size(); i++){//没有优化的地图点跳过if(vbNotIncludedMP[i])continue;//提取地图点MapPoint* pMP = vpMP[i];//如果位坏的地图点跳过if(pMP->isBad())continue;//转换类型提取地图点g2o::VertexSBAPointXYZ* vPoint = static_cast<g2o::VertexSBAPointXYZ*>(optimizer.vertex(pMP->mnId+maxKFid+1));//判定是否回环if(nLoopKF==0){//无回环就默认当前位姿pMP->SetWorldPos(Converter::toCvMat(vPoint->estimate()));pMP->UpdateNormalAndDepth();}else//若出现回环要提取估计值进行回环检测{pMP->mPosGBA.create(3,1,CV_32F);Converter::toCvMat(vPoint->estimate()).copyTo(pMP->mPosGBA);pMP->mnBAGlobalForKF = nLoopKF;}}//Points 地图点特征点}//BA优化

ORB-SLAM2学习笔记——BundleAdjustment函数相关推荐

  1. python函数是一段具有特定功能的语句组_Python学习笔记(五)函数和代码复用

    本文将为您描述Python学习笔记(五)函数和代码复用,具体完成步骤: 函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Pyth ...

  2. Python学习笔记:函数(Function)

    Python学习笔记:函数(Function) 一.函数基本概念 函数是Python里组织与重用代码最重要的方法.一般来说,如果你期望多次重复相同或相似的代码,写一个可重用的函数可能是值得的.函数通过 ...

  3. php中声明一个函数,php学习笔记之 函数声明

    /* 函数定义: * 1.函数是一个被命名的 * 2.独立的代码段 * 3.函数执行特定任务 * 4.并可以给调用它的程序返回一个值 * * 函数的优点: * 1.提高程序的重用性 * 2.提高程序的 ...

  4. Matlab学习笔记 figure函数

    Matlab学习笔记 figure函数 matlab中的 figure 命令,能够创建一个用来显示图形输出的一个窗口对象.每一个这样的窗口都有一些属性,例如窗口的尺寸.位置,等等.下面一一介绍它们. ...

  5. JAVA学习笔记五---函数

    JAVA学习笔记五---函数 5.1 方法的学习 编写一个程序,求圆的周长和面积. package practice; /*** 编写一个程序,求圆的周长和面积.* @author iszhangyo ...

  6. MySQL学习笔记—自定义函数

    MySQL学习笔记-自定义函数 注释语法: MySQL服务器支持3种注释风格: 从'#'字符从行尾. 从'– '序列到行尾.请注意'– '(双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如 ...

  7. matlab机器人工具箱学习笔记——ikine函数

    matlab机器人工具箱学习笔记--ikine函数 ikine函数用法 使用实例 链接: https://blog.csdn.net/weixin_42596724/article/details/8 ...

  8. 《JavaScript语言精粹》学习笔记(函数(2))

    <JavaScript语言精粹>学习笔记(函数(2)) 函数(Functions) 参数(Arguments) 当参数被调用时,会得到一个"免费"的参数数组argume ...

  9. matlab 调用子函数返回值,matlab学习笔记13_1 函数返回值

    一起来学matlab-matlab学习笔记13函数 13_1 函数返回值 觉得有用的话,欢迎一起讨论相互学习~Follow Me 函数返回一个值 返回值不必使用return语句,而是直接将需要返回的变 ...

  10. Python学习笔记12_函数

    Python学习笔记12_函数 文章目录 Python学习笔记12_函数 1.函数定义 2.函数调用 3.函数的参数 3.1.可更改对象和不可更改对象参数 3.2.必需参数(位置参数) 3.3.关键字 ...

最新文章

  1. 一分钟了解阿里云产品:阿里云解析五大热点技术问题分析
  2. Hitpoint:外贸企业如何选择合适的ERP系统
  3. linux vector 头文件,LINUX 之Vector用法
  4. 二次扩增产物条带弥散_PCR实验操作常见解决方法
  5. 大小字节序的深入理解和鉴定系统字节序方法
  6. 《数据结构》算法与算法设计
  7. 目标跟踪经典论文阅读(1)MOSSE
  8. matlab xticklabel 旋转,在Matlab中,如何实现xticklabel的旋转?转
  9. 9x9九宫格java_9x9九宫格数字填写规律
  10. 优化移动网站的9大窍门(转)
  11. Origin图选择性粘贴到word出现问题,提示‘word出现问题’解决方法
  12. 一种可大规模定向钓鱼携程旅游网千万用户的***过程重放(转载自wooyun)
  13. 网络准入控制 — 保护网络安全
  14. BZOJ 2002 HNOI2010 弹飞绵羊 分块
  15. 网站建设服务器拼租服务器好还是独立服务器好
  16. b站服务器故障修复,“B站崩了”官方回应:服务器机房故障!现已恢复!
  17. libsvm的使用svm-scale和svm-train与svm-predict
  18. java.lang.Class:是反射的源头
  19. 创建在Linux上运行的 .NET Core 应用程序(matlab封装的dll文件)
  20. python 图片识别服装_[Python设计模式] 第6章 衣服搭配系统——装饰模式

热门文章

  1. jscript php,PHP, JScript和VBScript函数和类的语法
  2. BlackBerry不能上网问题解决方案
  3. coreldraw x5安装视频教程_图形设计必备软件:CorelDRAW
  4. 简单酷炫css3动画效果,CSS3使用Animate.css制作超炫的动画效果
  5. yeezy350灰橙_Yeezy 350V2 Grey Orange 侃爷椰子350 灰橙 特价
  6. 你的电脑或移动设备不支持Miracast
  7. ShoeBox制作字体
  8. 上门洗车小程序/APP功能介绍
  9. 北京航空航天大学计算机学院 赵,北京航空航天大学计算机学院计算机应用技术导师介绍:夏春和...
  10. 图像增强(1-灰度级变换)—内涵MATLAB源码