首页 > 其他分享 > cereas学习(0-1) 代价函数CostFunction

cereas学习(0-1) 代价函数CostFunction

时间:2023-01-03 01:11:07浏览次数:47  
标签:ceres const 函数 cereas pt3 observed 参数 代价 CostFunction

代价函数CostFunction

与其他非线性优化工具包一样,ceres的性能很大程度上依赖于导数计算的精度和效率。这部分工作在ceres中称为 CostFunction

ceres提供了许多种 CostFunction模板,较为常用的包括以下三种:

1、自动导数(AutoDiffCostFunction):由ceres自行决定导数的计算方式,最常用的求导方式。

2、数值导数(NumericDiffCostFunction):由用户手动编写导数的数值求解形式,通常在残差函数的计算使用无法直接调用的

      库函数,导致调用AutoDiffCostFunction类构建时使用;但手动编写的精度和计算效率不如模板类,因此不到不得已,官方并不建议使用该方法。

3、解析导数(Analytic Derivatives):当导数存在闭合解析形式时使用,用于可基于CostFunciton基类自行编写;但由于需要自行管理残差和

      雅克比矩阵,除非闭合解具有具有明显的精度和效率优势,否则同样不建议使用

 

以看出,ceres官方极力推荐用户使用自动求导方式AutoDiffCostFunction,这里也主要以AutoDiffCostFunction为例说明。

AutoDiffCostFunction为模板类,构造函数如下:

ceres::AutoDiffCostFunction<CostFunctor, int residualDim, int paramDim>(CostFunctor* functor);

  模板参数依次为仿函数(functor)类型CostFunctor,残差维数residualDim和参数维数paramDim,接受参数类型为仿函数指针CostFunctor*

仿函数CostFunctor

仿函数的本质为结构体struct或者类class,由于重载了()运算符,使得其能够具有和函数一样的调用行为,因此被称为仿函数。

ceres中采用仿函数来表示残差的计算过程,这里我们以SLAM中经典的重投影误差为例,分析仿函数的典型定义方法。

这里由于我们只是举一个简单的例子,因此忽略相机坐标系向像素坐标系的转换过程,将重投影误差定义为归一化图像坐标系下的平面位置差:

该误差函数对应的仿函数如下(这里采用的是struct定义方式,采用class只需要按对应格式重写即可。)

主要包括 构造函数、重载操作符() 和 工厂函数三部分:

struct Reprojection{
	// 构造函数,传递用于计算误差的测量值
	Reprojection(double observed_u, double observed_v):
			observed_u_(observed_u), observed_v_(observed_v){}
 
	// 重载()操作符,用于计算误差
 	template <typename T>
	bool operator()(const T* const camera, const T* const pt3_w, T* residual)const 
	{
		T pt3_c[3]; //相机坐标系下的坐标
  
        // 世界坐标系到相机坐标系的转换
        T rvec[3] = {camera[0], camera[1], camera[2]};
        ceres::AngleAxisRotatePoint(rvec, pt3_w, pt3_c);
 
        pt3_c[0] += camera[3]; 
        pt3_c[1] += camera[4]; 
        pt3_c[2] += camera[5];
 
        // Z = 1     
        T x_normalized = -pt3_c[0] / pt3_c[2];
        T y_normalized = -pt3_c[1] / pt3_c[2];
		
		residual[0]=observed_u - x_normalized;
		residual[1]=observed_v - y_normalized;
		
		return true;
	}
 
 	// 工厂模式函数
 	static ceres::CostFunction* create(const double observed_u, const double observed_v){
        return(new ceres::AutoDiffCostFunction<ReprojectionError3D, 2, 9, 3>(
            new Reprojection(observed_u,observed_v)));
    }
	// 用于存储测量值的成员变量
	double observed_u_;
	double observed_v_;
};

  

构造函数(可选)

误差函数中的参数包括: 已知参数和待优化参数两部分,其中待优化参数由 Problem::AddResidualBlock() 统一添加和管理,

而 已知参数则在仿函数创建时通过构造函数传入,若优化问题没有已知参数,则不需要编写构造函数。在本例中,已知参数是相

机坐标系下的特征点二维坐标 p=[u,v]T,因此构造函数接受两个double型数据,并将其存入结构体的成员变量observed_uobserved_v中。

重载操作符()(必有)

操作符()是一个模板方法,返回值为bool型,接受参数为待优化变量和残差变量。待优化变量的传入方式应和 Probelm::AddResidualBlock() 一致,

即若Probelm::AddResidualBlock()中一次性传入变量数组指针,此处亦应该一次性传入变量数组指针;若Probelm::AddResidualBlock()变量

是依次传入,此处亦应该依次传入,且保证变量传入顺序一致。同时需要注意的是,该操作符的输入和输出变量统一为模板类型T,由于在编程过程中我们

会使用大量的开源算法库,而这些算法库具有自己独有的数据类型且各不相同(例如Eigen的矢量为Vector类型,矩阵为Matrix类型;OpenCV矢量为Point类型,

矩阵为Mat类型),在传入矢量或矩阵时需要尤其注意这一点(一般统一转化为double型数组)。

由于在优化过程中,我们不希望因为程序的误操作导致操作符()重载的内容被修改,因此需要为函数体加上const关键字修饰。同理,在残差的计算过程中,

为了避免除ceres优化之外的误操作引起待优化变量的改变,需要同时使用const关键字修饰参数类型和参数名保证类型和内容均不变;而residual只需要

保证类型不变,参数每次都是可变的,因此只需要使用const修饰类型T即可。

工厂函数(可选)

对于每一个新的量测来说,CostFunction 的构造方式是完全一致的,为了避免每次重复创建实例和析构实例,可以采用工厂模式,即该类提供一个静态的成员

函数用于创建CostFunction对象指针。本例中create()函数接受量测信息observed_uovserved_v并返回一个AutoDiffCostFunction对象指针。

标签:ceres,const,函数,cereas,pt3,observed,参数,代价,CostFunction
From: https://www.cnblogs.com/gooutlook/p/17020937.html

相关文章

  • cereas学习(1)min(10-x)平方
     http://ceres-solver.org/nnls_tutorial.html     structCostFunctor{template<typenameT>booloperator()(constT*constx,T*residual)......
  • cereas学习(2) 鲍威尔函数 多项式
      structF4{template<typenameT>booloperator()(constT*constx1,constT*constx4,T*residual)const{//f4=sqrt(10)(x1-x4)^2r......
  • 【随机接入】基于随机接入代价的异构网络速率分配算法
    1.软件版本matlab2013b2.本算法理论知识在协作传输中,把业务流分拆到不同网络进行传输可解决单一网络无法传输的问题,同时降低接入阻塞率并提高网络利用率。随机接入......
  • 每天进步一点点《ML - 正则化代价函数》
    本系列MachineLearning的学习博文很大部分全是受教于AndrewNg的Stanford录制的ML视频,我的男神。一:欠拟合(Underfitting)与过拟合(Overfitting)机器学习的目的就是通过一......
  • 我还是太年轻了,冲动的代价太大了
    人生就是这么"有趣",由于我没有恋爱经验,自身性格还比较冲动,导致错过了很多优质的对象,每次即便遇到了心动的人,我都不敢去说话。事件起因人生就是这么"......
  • 算法题-完美的代价--回文串
    算法题-完美的代价--回文串问题描述回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你......
  • 求构成正方形的最小代价
    题目描述牛牛有4根木棍,长度分别为a,b,c,d。羊羊家提供改变木棍长度的服务,如果牛牛支付一个硬币就可以让一根木棍的长度加一或者减一。牛牛需要用这四根木棍拼凑一个正方形......
  • 我还是太年轻了,冲动的代价太大了
    人生就是这么"有趣",由于我没有恋爱经验,自身性格还比较冲动,导致错过了很多优质的对象,每次即便遇到了心动的人,我都不敢去说话。昨天家里人给我介绍了对象,以前还好不想谈,现在......