Ceres Solver通过最小化残差平方和求解非线性最小二乘问题,需建模残差函数、配置依赖与CMake、定义AutoDiffCostFunction、构建Problem并调用Solve;注意初值选取、维度匹配与求导验证。

用 Ceres Solver 做非线性最小二乘优化,核心是把问题建模为残差函数,再交给 Ceres 自动求导、迭代求解。它不直接优化目标函数,而是最小化所有残差的平方和,适合拟合、SLAM、标定等场景。
安装与基础配置
Ceres 依赖 Eigen、glog、gflags 和 SuiteSparse(可选)。推荐用 CMake 构建:
- Linux/macOS 下用 apt install 或 brew install 安装依赖,再从源码编译 Ceres(开启 -DBUILD_SHARED_LIBS=ON)
- Windows 可用 vcpkg:vcpkg install ceres[cxx17],然后在 CMakeLists.txt 中 find_package(Ceres REQUIRED)
- 确保项目中包含头文件:#include
,链接库时加 target_link_libraries(your_target PRIVATE ceres)
定义残差代价函数(Cost Function)
每类优化变量对应一个残差块(Residual Block),需继承 ceres::CostFunction 或更常用的是用 AutoDiffCostFunction 自动求导:
- 写一个仿函数(functor),重载 operator(),输入参数块(const double* const*),输出残差(double*)
- 例如拟合直线 y = ax + b,残差为 y_i − (a·x_i + b),就构造一个含 2 个参数(a,b)、1 个残差项的 CostFunction
- 用 new ceres::AutoDiffCostFunction
(new LineResidual(x, y)) 创建自动微分版本,省去手算雅可比
构建并求解优化问题
把变量、残差、约束组装成 ceres::Problem,再调用 Solve():
立即学习“C++免费学习笔记(深入)”;
- 声明参数块(如 double a = 1.0, b = 0.0;),用 problem.AddParameterBlock(&a, 1) 注册
- 对每组数据调用 problem.AddResidualBlock(cost_function, loss_function, &a, &b);loss_function(如 Cauchy 或 Huber)可抑制异常值影响
- 配置 ceres::Solver::Options:设 options.linear_solver_type = ceres::DENSE_QR;(小规模)、options.minimizer_progress_to_stdout = true; 查看迭代过程
- 调用 ceres::Solve(options, &problem, &summary),结果存在原始变量中,summary 包含收敛状态、迭代次数、最终代价等
常见技巧与注意事项
实际使用中容易卡在初值、发散或收敛慢,这些点很关键:
- 参数初值尽量靠近真实值——Ceres 是局部优化器,差太远可能陷入次优或不收敛
- 检查残差维度是否匹配:残差数必须等于 CostFunction::num_residuals(),参数块大小要和 parameter_block_sizes 一致
- 开启 options.check_gradients = true; 可验证自动求导是否正确(仅调试用,会变慢)
- 大问题考虑用 SparseNormalCholesky 求解器,或启用 options.use_explicit_schur_complement = true; 加速 BA 类问题
不复杂但容易忽略细节,把残差写对、初值设稳、求解器配合适,Ceres 就能稳定跑出高精度结果。











