Ceres
使用Ceres求解非线性优化问题,主要分为三个部分:
- 第一部分:构建代价函数 - Cost_Functor- 1 
 2
 3
 4
 5
 6
 7
 8- // 定义一个实例化时才知道的类型T 
 template <typename T>
 // 运算符()的重载,用来得到残差fi
 bool operator()(const T* const x, T* residual) const {
 residual[0] = T(10.0) - x[0];
 return true;
 }
- 第二部分:构建最小二乘问题 - problem- 1 
 2
 3
 4
 5- Problem problem; 
 // 使用自动求导,第一个1是输出维度(残差项),第二个1是输入维度(优化项)
 CostFunction* cost_function = new AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
 // 添加误差项,NULL表示不使用核函数,x是优化项
 problem.AddResidualBlock(cost_function, NULL, &x);
- 第三部分:求解器参数配置 - Solver- 1 
 2
 3
 4
 5
 6
 7- Solver::Options options; 
 options.linear_solver_type = ceres::DENSE_QR; //配置增量方程的解法,稠密的QR分解
 options.minimizer_progress_to_stdout = true;//输出到cout
 Solver::Summary summary;//优化信息
 Solve(options, &problem, &summary);//求解
 cout << summary.BriefReport() << "\n";//输出优化的简要信息
使用核函数:数据中往往存在离群点,离群点会对寻优结果造成影响,这时可以使用一些损失核函数来对离群点的影响加以消除,Ceres库中提供的核函数主要有:TrivialLoss 、HuberLoss、 SoftLOneLoss 、 CauchyLoss。
| 1 | // 使用核函数 | 


g2o
用g2o优化库来进行优化的步骤如下:
- 定义节点和边的类型,通常在默认的基础类型上做修改 - 定义顶点,顶点的基类为 - g2o::BaseVertex<优化变量维度,数据类型>- 1 - class CurveFittingVertex: public g2o::BaseVertex<3, Eigen::Vector3d> - 顶点的更新函数 - oplusImpl:定义增量加法,因为优化变量和增量之间并不一定是线性叠加的关系,如位姿变换。- 定义边, 本例中的边为一元边,基类为 - g2o::BaseUnaryEdge<观测值维度,数据类型,连接顶点类型>- 1 - class CurveFittingEdge: public g2o::BaseUnaryEdge<1, double , CurveFittingVertex> - 误差项计算函数 - computeError:计算预测值和观测值的误差。估计值是基于当前对优化变量的estimate计算出的,观测值是直接获取的,如本例中的y值。
- 构建图模型 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- // vertex 
 g2o::VertexSE3Expmap* pose = new g2o::VertexSE3Expmap(); // camera pose
 pose->setId( index );
 pose->setEstimate( expression );
 optimizer.addVertex ( pose );
 // edge
 g2o::EdgeProjectXYZ2UV* edge = new g2o::EdgeProjectXYZ2UV();
 edge->setId ( index );
 edge->setVertex ( 0, point );
 edge->setVertex ( 1, pose );
 edge->setMeasurement ( Eigen::Vector2d ( p.x, p.y ) ); // 导入观测值
 edge->setParameterId ( 0,0 );
 edge->setInformation ( Eigen::Matrix2d::Identity() ); // 设置信息矩阵
 optimizer.addEdge ( edge );- 信息矩阵 - edge->setInformation(信息矩阵):因为最终的优化函数是$\sum e_i^T \Sigma^{-1}e_i$,是误差项和信息矩阵乘积的形式。
- 优化器配置 - 矩阵块Block
- 优化算法solver
- 图模型optimizer
 
- 执行优化