RootBA源码解读2—问题构建

15 篇文章 1 订阅

本文想讨论rootBA代码中BA问题构造的过程。

float和double的实例化中,构造的流程是一致的。而这里,主要需要关注的就是load_normalized_bal_problem<datatype>这个模板类的构建

#ifdef ROOTBA_INSTANTIATIONS_FLOAT
      // load dataset
      auto bal_problem = load_normalized_bal_problem<float>(
          options.dataset, &summary.dataset, &summary.timing);

      // run solver
      bundle_adjust_manual(bal_problem, options.solver, &summary.solver,
                           &summary.timing);

      // postprocess
      bal_problem.postprocress(options.dataset, &summary.timing);
#else
      LOG(FATAL) << "Compiled without float support.";

它有很多种重载形式,我们需要关注的是如下的形式

template <class Scalar>
BalProblem<Scalar> load_normalized_bal_problem(
    const BalDatasetOptions& options, DatasetSummary* dataset_summary,
    PipelineTimingSummary* timing_summary)

通过配置文件中参数的选择,我们可以使用不同的求解器

  BalProblem<double> bal_problem;
  bal_problem.set_quiet(options.quiet);
  switch (input_type) {
    case BalDatasetOptions::DatasetType::ROOTBA:
      bal_problem.load_rootba(options.input);
      break;
    case BalDatasetOptions::DatasetType::BAL:
      bal_problem.load_bal(options.input);
      break;
    case BalDatasetOptions::DatasetType::BUNDLER:
      bal_problem.load_bundler(options.input);
      break;

 我们关注一下lood_bal的加载方式,它是针对bal数据集进行适配后的接口

template <typename Scalar>
BalProblem<Scalar>::BalProblem(const std::string& path) {
  load_bal(path);
}

template <typename Scalar>
void BalProblem<Scalar>::load_bal(const std::string& path) {
  FILE* fptr = std::fopen(path.c_str(), "r");
  if (fptr == nullptr) {
    LOG(FATAL) << "Could not open '{}'"_format(path);
  };

  try {
    // parse header
    int num_cams;
    int num_lms;
    int num_obs;
    fscan_or_throw(fptr, "%d", &num_cams);
    fscan_or_throw(fptr, "%d", &num_lms);
    fscan_or_throw(fptr, "%d", &num_obs);
    CHECK_GT(num_cams, 0);
    CHECK_GT(num_lms, 0);
    CHECK_GT(num_obs, 0);

这里做的事情其实很简单,就是读取bal数据集,然后得到landmark的位置和camera的位姿相关信息,存储到BalProblem的类成员中    cameras_, landmarks_,值得注意的是,观测存储到了landmarks_中。并且,因为Bal使用了z轴向内,y轴向上的相机坐标系,代码里还一顿操作把两个轴都换成了反方向。

此外,作者load problem的两个参数dataset_summary 和 timing_summary是两个结构体,目的是为了汇报dataset的数据和时间的数据。

在加载完数据后,作者还添加了预处理操作。包括对于问题normalize,添加绕动,和过滤太近的特征点。

  // normalize to fixed scale and center (as double, since there are some
  // overflow issues with float for large problems)  
if (options.normalize) {
    bal_problem.normalize(options.normalization_scale);
  }

  // perturb state if sigmas are positive
  bal_problem.perturb(options.rotation_sigma, options.translation_sigma,
                      options.point_sigma, options.random_seed);

  // Filter observations of points closer than threshold to the camera
  bal_problem.filter_obs(options.init_depth_threshold);

总结一下,问题加载的部分,作者主要目的是为了对于不同的数据集类型对于接口进行重载,适配。

这部分比较有意思的地方在于,作者把问题的构建和求解分离开来。另外,利用结构体传参记录数据信息,求解耗时等参数,也是非常细心的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值