安装
ceres是google库,首先安装相关依赖1
2
3sudo apt-get install -y libatlas-base-dev
sudo apt-get install -y liblapack-dev libsuitesparse-dev libcxsparse3.1.2 libgflags-dev
sudo apt-get install -y libgoogle-glog-dev libgtest-dev
如果使用Ubuntu18.04,安装libcxsparse3.1.2
可能出错,ubuntu从18.04版本开始,libcxsparse这个包的名称改为libcxsparse3
。具体方法参考安装Ceres相关依赖时libcxsparse3.1.2报错
如果安装时找不到 cxsparse 或者其他的lib,需要添加下面的源1
sudo vim /etc/apt/sources.list
把下面的源粘贴到source.list的最上方: deb http://cz.archive.ubuntu.com/ubuntu trusty main universe
更新一下: sudo apt-get update
, 然后再进行第一步的安装。
从github上下载,这里要注意ceres的版本和Eigen是搭配的,ceres版本越新,对Eigen的版本要求也越新,它的CMakeLists
里有提示,所以不要安装最新的。 安装2.0.0 即可
下载解压后执行老一套命令:1
2
3
4
5mkdir build
cd build
cmake ..
make
sudo make install
配置 CMake
安装官方的说明配置是错误的,应该是这样:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15find_package(Ceres REQUIRED)
INCLUDE_DIRECTORIES(/usr/include/eigen3)
include_directories(
${catkin_INCLUDE_DIRS}
# 这行可以没有
${CERES_INCLUDE_DIRS}
)
add_executable(program src/program.cpp)
target_link_libraries(program
${catkin_LIBRARIES}
${CERES_LIBRARIES}
)
如果这样报错,找不到ceres,就加上set(Ceres_DIR "/usr/local/lib/cmake/ceres")
, 也可能是 /usr/local/lib/cmake/ceres
ceres使用LM或狗腿算法,求解参数的数据类型只支持 double*
。Ceres相对于g2o的缺点仅仅是依赖的库多一些(g2o仅依赖Eigen).但是可以直接对数据进行操作
ceres是求解给定函数的最小值
Solver::Options
Solver::Options::trust_region_strategy_type
可以取LEVENBERG_MARQUARDT
或DOGLEG
Solver::Options::use_inner_iterations
设为True,可以启用 Ruhe & Wedin的非线性推广的算法II。这个版本的Ceres具有更高的迭代复杂度,但是每次迭代都显示更好的收敛行为。把Solver::Options::num_threads
设为最大值是非常值得推荐的minimizer_progress_to_stdout
num_threads: 设置使用的线程,但有时线程少反而用时更少,不明白为什么
linear_solver_type
对于非线性最小二乘问题,最终转化为求解方程
Ceres提供了很多计算的方法,这就涉及Solver::Options::linear_solver_type
的取值问题
- DENSE_QR
默认值。 适合使用稠密雅可比矩阵的小规模问题(几百个参数和几千个残差),也就是使用Eigen库的稠密矩阵QR分解。如果ceres优化问题不是SLAM的大型后端,不是稀疏问题,使用DENSE_QR
- DENSE_NORMAL_CHOLESKY & SPARSE_NORMAL_CHOLESKY
大规模的非线性最小二乘问题通常是稀疏的。对于这种情况使用稠密QR分解是低效率的,改用Cholesky因式分解,它有两种变体 - 稀疏和密集。
DENSE_NORMAL_CHOLESKY
是执行正规方程的稠密Cholesky分解。 Ceres使用Eigen稠密的LDLT
因式分解算法。
SPARSE_NORMAL_CHOLESKY
是执行正规方程的稀疏Cholesky分解,这为大量稀疏问题节省了大量的时间和内存消耗。Ceres使用SuiteSparse
或 CXSparse
库中的稀疏Cholesky分解算法 或 Eigen中的稀疏Cholesky分解算法。
如果Ceres编译时支持了这三个库,那么linear_solver_type
默认值是SPARSE_NORMAL_CHOLESKY
,否则就是DENSE_QR
。使用最多的是DENSE_QR
,cartographer前端的ceres scan mather用的也是DENSE_QR
CGNR : 使用共轭梯度法求解稀疏方程
DENSE_SCHUR & SPARSE_SCHUR : 适用于BA问题
ceres::Solver::Summary 的常用函数
ceres::Solver::Summary summary;
- double Solver::Summary::total_time_in_seconds. Time (in seconds) spent in the solver
直接使用summary.total_time_in_seconds
int Solver::Summary::num_threads_given: Number of threads specified by the user for Jacobian and residual evaluation.
int Solver::Summary::num_threads_used
Number of threads actually used by the solver for Jacobian and residual evaluation. This number is not equal to Solver::Summary::num_threads_given
if none of OpenMP
or CXX_THREADS
is available.
以上两个线程的参数是由Options::num_threads
决定的,如果设置太大,这两个参数就会不同,只会用最大线程数。
min_linear_solver_iteration 和 max_linear_solver_iteration:线性求解器的最小/最大迭代次数,默认为0/500,一般不需要更改
max_num_iterations : 默认是50。求解器的最大迭代次数,并不是越大越好。对于SLAM前端的实时性有要求,所以
max_num_iterations
不能太大,ALOAM里设置为4bool Solver::Summary::IsSolutionUsable() const
算法返回的结果是否数值可靠。 也就是Solver::Summary:termination_type
是否是CONVERGENCE
, USER_SUCCESS
或者 NO_CONVERGENCE
,也就是说求解器满足以下条件之一:
- 达到了收敛误差
- 达到最大迭代次数和时间
- user indicated that it had converged
通过实验发现除了多线程以及 linear_solver_type
,别的对优化性能和结果影响不是很大
BriefReport
FullReport
例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time
0 1.259266e+05 0.00e+00 5.00e+04 0.00e+00 0.00e+00 1.00e+04 0 1.91e-05 1.26e-04
1 2.468045e+04 1.01e+05 2.69e+02 1.31e+01 1.00e+00 3.00e+04 1 5.60e-05 2.02e-04
2 2.467825e+04 2.20e+00 1.17e+00 5.00e-02 1.00e+00 9.00e+04 1 2.29e-05 2.37e-04
Solver Summary (v 2.0.0-eigen-(3.3.4)-lapack-suitesparse-(5.1.2)-cxsparse-(3.1.9)-eigensparse-no_openmp)
Original Reduced
Parameter blocks 4 3
Parameters 12 9
Residual blocks 5 5
Residuals 15 15
Minimizer TRUST_REGION
Sparse linear algebra library SUITE_SPARSE
Trust region strategy LEVENBERG_MARQUARDT
Given Used
Linear solver SPARSE_NORMAL_CHOLESKY SPARSE_NORMAL_CHOLESKY
Threads 1 1
Linear solver ordering AUTOMATIC 3
Cost:
Initial 1.259266e+05
Final 2.467825e+04
Change 1.012484e+05
Minimizer iterations 3
Successful steps 3
Unsuccessful steps 0
Time (in seconds):
Preprocessor 0.000106
Residual only evaluation 0.000009 (3)
Jacobian & residual evaluation 0.000026 (3)
Linear solver 0.000053 (3)
Minimizer 0.000166
Postprocessor 0.000004
Total 0.000276
Termination: CONVERGENCE (Function tolerance reached. |cost_change|/cost: 6.530805e-10 <= 1.000000e-06)
Initial Cost 从 1.259266e+05 变为 Final Cost的 2.467825e+04,变化不够大。 如果 Initial cost 和 Final Cost 差别很小,说明优化之前的数据已经足够好
参考:
官方教程学习笔记(十三)