ceres库(一) 安装和介绍

安装

ceres是google库,首先安装相关依赖

1
2
3
sudo 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
5
mkdir build
cd build
cmake ..
make
sudo make install

配置 CMake

安装官方的说明配置是错误的,应该是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
find_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_MARQUARDTDOGLEG

  • 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使用SuiteSparseCXSparse库中的稀疏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里设置为4

  • bool Solver::Summary::IsSolutionUsable() const

算法返回的结果是否数值可靠。 也就是Solver::Summary:termination_type是否是CONVERGENCE, USER_SUCCESS 或者 NO_CONVERGENCE,也就是说求解器满足以下条件之一:

  1. 达到了收敛误差
  2. 达到最大迭代次数和时间
  3. 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
44
iter      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 差别很小,说明优化之前的数据已经足够好

参考:
官方教程学习笔记(十三)