《视觉slam十四讲》初学小白笔记(6)

 看了两天的公式,头都大了。什么状态估计,最小二乘(不得不感叹一句,数学好差啊~还好有个牛皮的师兄给我答疑解惑)

今天看着例程敲了一下Ceres的代码,基本是个固定模板https://blog.csdn.net/MyArrow/article/details/82906738

不能深究,不然发现自己又有一堆一堆不懂的东西,可怕~

慢慢学,之后再来填坑~

#include<iostream>
#include<opencv2/core/core.hpp>
#include<ceres/ceres.h>
#include<chrono> //计时

using namespace std;

/*
 * 第一步:定义残差函数fi:定义一个代价函数的结构体(struct),在结构体内重载()运算符
 * 第二步:创建一个CostFunction(把fi作为其参数)
 * 第三步:增加一个残差块(Problem.AddResidualBlock)
 * 第四步:问题求解(Problem.Solve)
 * 
 */


//代价函数的计算模型
struct CURVE_FITTING_COST{
  CURVE_FITTING_COST(double x,double y):_x(x),_y(y){}	//struct的用法
  //残差的计算
  template <typename T>		//固定模板,T是一个类型
  bool operator()(const T* const abc,	//参数模型,3维
		  T* residual) const	//残差
    {
      
      //y-exp(ax^2+bx+c)
      residual[0]=T(_y)-ceres::exp(abc[0]*T(_x)*T(_x)+abc[1]*T(_x)+abc[2]);
      return true;      
    }
    const double _x,_y;
};

int main(int agrc,char** agrv){
  double a=1.0,b=2.0,c=1.0;	//真实参数值
  int N=100;			//数据点
  double w_sigma=1.0;		//噪声点sigma的值
  cv::RNG rng;			//opencv的随机数产生器
  double abc[3]={0,0,0};	//abc的参数估计
  
  vector<double>x_data,y_data;
  
  cout<<"generating data(生成数据):"<<endl;
  for(int i=0;i<N;i++){
    double x=i/100.0;
    x_data.push_back(x);
    y_data.push_back(exp(a*x*x+b*x+c)+rng.gaussian(w_sigma));	//加上高斯噪声
    cout<<x_data[i]<<" "<<y_data[i]<<endl;  
  }
  
  //构建最小二乘问题(ceres的核心问题,还不是很懂)
  ceres::Problem problem;
  for(int i=0;i<N;i++){
    //AddResidualBlock()顾名思义主要用于向Problem类传递残差模块的信息,函数原型如下,
    //传递的参数主要包括代价函数模块、损失函数模块和参数模块。
    problem.AddResidualBlock(		
      //自动求导的代价函数AutoDiffCostFunction,模板参数:误差类型、输入维度(x)、输出维度(y)
      new ceres::AutoDiffCostFunction<CURVE_FITTING_COST,1,3>( 
	new CURVE_FITTING_COST(x_data[i],y_data[i])),  //代价函数模块
	nullptr,abc);
  }
  
  //配置求解器
  ceres::Solver::Options options;	
  options.linear_solver_type=ceres::DENSE_QR;	//求解增量方程
  options.minimizer_progress_to_stdout=true;	//输出到cout
  
  ceres::Solver::Summary summary;		//优化信息
  chrono::steady_clock::time_point t1=chrono::steady_clock::now();	//计时
  
  ceres::Solve(options,&problem,&summary);
  chrono::steady_clock::time_point t2=chrono::steady_clock::now();	//开始优化
  chrono::duration<double> time_used=chrono::duration_cast<chrono::duration<double>>(t2-t1);
  cout<<"solve time over="<<time_used.count()<<" s"<<endl;
  
  cout<<summary.BriefReport()<<endl;
  cout<<"estimate a,b,c";
  for(auto a:abc) cout<<a<<" ";
  cout<<endl;
  
  return 0;
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值