ceres优化库的一点总结(问题构建总结和求导方式的分析)

1.Ceres中求解一个优化问题的结构

背景:在SLAM中,很多问题都是在求解Translation(包含旋转和平移量),因此这里以其为代表,来分析使用ceres如何对其近求导。

void Calibrator::Optimize(Eigen::Matrix4d& tf)
{
   
   
    //待优化参数分别为rotation和t
    Eigen::Matrix3d rot = T_.topLeftCorner(3,3);
    Eigen::Quaterniond q (rot);
    Eigen::Vector3d p = T_.topRightCorner(3,1);

    ceres::Problem problem;
    ceres::Solver::Summary summary;
    ceres::Solver::Options options;
    ceres::LossFunction* loss_function_edge (new ceres::SoftLOneLoss(1));

    ceres::LocalParameterization* quaternion_local_parameterization =
        new ceres::EigenQuaternionParameterization;

    for(const auto& ply : polygons_)
    {
   
   
        // add edge 误差来源:每一条3D点云边上的点,到2D平面的直线的距离
        for(uint32_t i=0; i<size_; i++)
        {
   
   
            if(ply.pc->edges[i].points.cols() == 0)
            {
   
   
                continue;
            }
            ceres::CostFunction* cost = new ceres::AutoDiffCostFunction<Edge2EdgeError, 1,4,3>(new Edge2EdgeError( K_, ply.pc->edges[i].points, ply.img->edges[ply.ids[i]].coef ));//
            problem.AddResidualBlock(cost, loss_function_edge,q.coeffs().data(), p.data());
        }
    }
    problem.SetParameterization(q.coeffs().data(), quaternion_local_parameterization);
    options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY;
    options.max_num_iterations = 5000;
    options.num_threads= boost::thread::hardware_concurrency() - 1;
    options.num_linear_solver_threads = options.num_threads;

    ceres::Solve(options, &problem, 
在使用Ceres求解非线性优化问题时,构建损失函数残差函数是关键步骤。以下是构建它们的具体方法: ### 构建残差函数 残差函数描述了模型预测值与实际观测值之间的差异。在Ceres中,残差函数通常通过定义一个结构体或类来实现,该结构体或类需要重载`operator()`运算符。 #### 自动求导方式 使用`AutoDiffCostFunction`时,残差函数的定义需要满足特定的模板要求。以下是一个简单的示例: ```cpp #include "ceres/ceres.h" #include <iostream> // 定义残差函数结构体 struct QuadraticCost { template <typename T> bool operator()(const T* const x, T* residual) const { residual[0] = T(10.0) - x[0]; return true; } }; int main(int argc, char** argv) { double x = 0.5; ceres::Problem problem; // 使用AutoDiffCostFunction自动计算雅可比矩阵 ceres::CostFunction* cost_function = new ceres::AutoDiffCostFunction<QuadraticCost, 1, 1>(new QuadraticCost); problem.AddResidualBlock(cost_function, nullptr, &x); ceres::Solver::Options options; options.linear_solver_type = ceres::DENSE_QR; options.minimizer_progress_to_stdout = true; ceres::Solver::Summary summary; ceres::Solve(options, &problem, &summary); std::cout << summary.BriefReport() << "\n"; std::cout << "x: " << x << "\n"; return 0; } ``` 在上述代码中,`QuadraticCost`结构体定义了残差函数,`operator()`接受一个输入参数`x`一个输出参数`residual`,并计算残差。 #### 手动求导方式 手动计算雅可比矩阵时,需要定义一个继承自`SizedCostFunction`的类,并实现`Evaluate`方法。以下是示例: ```cpp #include "ceres/ceres.h" #include <iostream> class QuadraticCostFunction : public ceres::SizedCostFunction<1, 1> { public: virtual ~QuadraticCostFunction() {} virtual bool Evaluate(double const* const* parameters, double* residuals, double** jacobians) const { const double x = parameters[0][0]; residuals[0] = 10 - x; if (jacobians != nullptr && jacobians[0] != nullptr) { jacobians[0][0] = -1; } return true; } }; ``` 在`Evaluate`方法中,需要计算残差雅可比矩阵。 ### 构建损失函数 损失函数用于处理异常值,Ceres提供了多种损失函数,如`TrivialLoss`、`HuberLoss`、`CauchyLoss`等。在添加残差块时,可以指定损失函数。以下是示例: ```cpp // 使用HuberLoss损失函数 ceres::LossFunction* loss_function = new ceres::HuberLoss(1.0); problem.AddResidualBlock(cost_function, loss_function, &x); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值