ceres求解BA第10章

1.前言
g2o是根据边来保存每一个代价函数,它是在边类中构造误差函数,构造边的时候,会设置顶点、测量值、协方差矩阵等。而在ceres中,用problem类型来构造最终的目标函数。先是使用AddResidualBlock来添加代价函数,代价函数和核函数等构造成目标函数。
在ceres中,代价函数就是误差项,目标函数是由很多误差项的范数的平方再各自乘以核函数除以2得到的。
2.定义代价函数类型,定义其create成员来使用ceres当中的AutoDiff特性
所谓的定义代价函数类型是定义了一个SnavelyReprojectionError.h文件,它的构造函数中用的成员变量是observed_x,observed_y,会把传入的值赋值给observed_x,observed_y,这两个值是测量值,在重载运算符()中,只有输入camera,point,residuals,那么camera,point就会计算出预测值,和测量值相减,就可以得到误差项。
而ceres::AutoDiffCostFunction的参数就是这个SnavelyProjectionError类和2,9,3,输入值就是SnavelyProjectionError类。
3.ceresBundle.cpp 添加代价函数
定义point_block_size和camera_block_size,这里是3和9
定义points和cameras指针,返回值分别是parameters_+cmear_block_size()*num_cameras_;和parameters_
定义观测值常量指针observations,返回值是2*num_observations_的列。observations数据不能更改。没有给出观测值的具体值啊,这个是要读取的。
根据观测值数量做一个for循环,定义代价函数指针cost_function.它的值形式就是SnavelyProjectionError.h的create函数,输入变量是observations[2*i+0],observations[2*i+1].
定义损失函数指针为loss_function,这里的损失函数类似于鲁棒核函数,也是用来怕不好的数据点影响迭代效果的。它的值为如果params.robustify是健壮的,就用HuberLoss(1.0)函数,这里的delta定位1.0.如果不健壮就为NULL.
定义数据指针camera,point为cameras+9*camera_index()[i]和points+3*point_index()[i];
point_index为num_observations_长度的列,camera_index同样。

然后往问题里添加代价函数就可以了。是这么添加的
problem->AddResidualBlock(cost_function,loss_function,camera,point)
只有放入代价函数,损失函数,放入camera,point这个SnavelyProjectionError.h就可以用到这两个值得到代价函数的形式。看problem.h可以看到,在problem类中,添加目标函数的变量都是指针形式,分别是代价函数,损失函数,x0和x1.
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1);
4.ceresBundle.cpp 用ParameterBlockOrdering来管理Schur的消元顺序
定义SetOrdering函数来做。在函数里分别定义
num_points,points_block_size,指针points,points值为parameters_ + camera_block_size() * num_cameras_; 跟之前一样。
还有num_cameras,camera_block_size,指针cameras.
如果参数的ordering值为"automatic",那么跳出函数,否则
定义ParameterBlockOrdering指针 ordering.
用ordering的AddElementToGroup对变量进行编号从而定义消元顺序。这里设置点云变量为0,相机变量为1.
先做points的循环
ordering->AddElementToGroup(points+point_block_size*i,0);
然后把ordering放到ceres的求解器options中
options->linear_solver_ordering.reset(ordering)
5.ceresBundle.cpp 设置优化策略
ceres设置优化策略等直接对Solver::Options的类型成员进行赋值就可以了,很方便。
这里设了一个setSolverOptionsFromFlags函数,变量有bal_problem用来提供各种参数值的,params用来判断的,options选择优化策略的。
来看options的几个参数值。
max_num_iterations:最大迭代次数
minimizer_progress_to_stdout:要不要输出到cout,如果输出,填true;
num_threads:用于计算的线程数目,可以加速雅克比矩阵的计算。
trust_region_strategy_type:下降策略的选取
linear_solver_type:增量方程如何求解,例如ceres::DENSE_QR.
设置好options之后,把它放入之前的SetOrdering函数,对schur消元进行排序。
6求解的设置
也还是options的参数
gradient_tolerance=1e-16;梯度
function_tolerance=1e-16:两次迭代之间目标函数之差的阈值。
定义统计信息summary,然后一次把options,&problem,&summary放入求解 函数solve就可以了。其中options是设置求解策略和阈值等的,problem是用来设置目标函数是怎么求得,summary是求解之后的统计信息。

 

时间: 2024-10-17 03:47:40

ceres求解BA第10章的相关文章

g2o求解BA 第10章

1.g2o_bal_class.h1.1 projection.hg2o还是用图模型和边,顶点就是相机和路标,边就是观测,就是像素坐标.只不过这里的相机是由旋转(3个参数,轴角形式,就是theta*nx,theta*ny,theta*ny),位移(3个参数),f,k1,k2.就是之前BA模型的实现.但是这里归一化平面坐标取得是负值,而且最后没有加cx,cy.具体实现在projection.h中的CamProjectionWithDistortion函数实现的,而其中世界坐标转成相机坐标是由rot

统计学习方法 李航---第10章 隐马尔可夫模型

第10章隐马尔可夫模型 隐马尔可夫模型(hidden Markov model, HMM)是可用于标注问题的统计学习模型,描述由隐藏的马尔可夫链随机生成观测序列的过程,属于生成模型. 10.1 隐马尔可夫模型的基本概念 定义10.1 (隐马尔可夫模型) 隐马尔可夫模型是关于时序的概率模型,描述由一个隐藏的马尔可夫链随机生成不可观测的状态随机序列,再由各个状态生成一个观测而产生观测随机序列的过程.隐藏的马尔可夫链随机生成的状态的序列,称为状态序列(state sequence):每个状态生成一个观

[摘录]第10章 培养胜过对手的力量

第五部分 谈判高手 优势秘籍力量.控制和影响,是每个人与别人交往时都会追求这些东西.不是吗?在进行谈判时,那些最有影响力火灾是最有力量的一方往往会在谈判时迫使对手做出更多的让步.如果你甘心让对手来操纵或影响你的话,显然你就很可能得不到自己想要的结果.另一方面,如果你直到哪些因素,能影响你的对手,并知道如何使用一些具体的方法来形成这种影响力,你就可以将形势控制在自己手中.权力本身也可以成为一种非常富有建设性的力量,当我们谈论权力时,我并不是指独裁者们用来祸害平民们的那种权力,我所说的权力实际上是一

10-11-基数排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第10章  内部排序 - 基数排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c        相关测试数据下载  链接? 数据

读《构建之法》第8、9、10章有感

第8章  需求分析 软件需求 用户的需求五花八门,作为一个软件团队要准确而全面地获取这些需求主要有以下四个步骤: 获取和引导需求.这一步骤也被叫做“需求捕捉”.软件团队需要为用户着想,设身处地,为用户引导出需求. 分析和定义需求.从各个方面获取的需求进行规整,定义需求的内涵从各个角度将需求量化. 验证需求.软件团队要跟利益相关者沟通,通过分析报告.技术原型.用户调查或演示等形式向他们验证软件团队对于这些需求的认知. 在软件产品的生命周期中管理需求. 竞争性需求分析的框架:1.N(需求) 2.A(

敏捷软件开发:原则、模式与实践——第10章 LSP:Liskov替换原则

第10章 LSP:Liskov替换原则    Liskov替换原则:子类型(subtype)必须能够替换掉它们的基类型(base type). 10.1 违反LSP的情形 10.1.1 简单例子 对LSP的违反导致了OCP的违反: struct Point { double x, y;} public enum ShapeType { square, circle }; public class Shape { private ShapeType type; public Shape(Shape

第10章-异常处理 --- 使用throw抛出异常

第10章-异常处理 --- 使用throw抛出异常 (一)抛出异常 如果需要在程序中自行抛出异常,则应使用throw语句,throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例. throw语句的语法格式如下: throw ExceptionInstance; 如果throw语句抛出的异常是Checked异常,则该throw语句要么处于try块里,显示捕获该异常,要么放在一个带throws声明抛出的方法中,即把该异常交给该方法的调用者处理;如果

第10章-异常处理 --- Checked异常和Runtime异常体系

第10章-异常处理 --- Checked异常和Runtime异常体系 Java的异常被分为两大类:Checked异常和Runtime异常(运行时异常).所有的RuntimeException类及其子类的实例被称为Runtime异常;不是RuntimeException类及其子类的异常实例则被称为Checked异常. 对于Checked异常的处理方法有如下两种: (1)当前方法明确知道如何处理该异常,程序应该用try...catch块来捕获该异常,然后在对应的catch块中修复该异常. (2)当

内部排序-第10章-《数据结构题集》习题解析-严蔚敏吴伟民版

//**留坑待填**// 一.基础知识题 10.1?以关键码序列(503,087,512,061,908,170,897,275,653,426)为例,手工执行以下排序算法,写出每一趟排序结束时的关键码状态: (1)直接插入排序:                            (2)希尔排序(增量d[1]=5): (3)快速排序:                                  (4)堆排序: (5)归并排序: