[Ceres]关于Problem的重要的类

Class Problem

Problem类应该是ceres中的核心.

Members Struct

Options

​ 结构体,优化的选项.

EvaluateOptions

​ 结构体,Evaluate函数的选项.

Members

internal::scoped_ptr< internal::ProblemImpl > problem_impl_

​ Class problem只是个接口,主要功能函数都在problem_impl_(Class ProblemImpl)完成.

Important Member Function

AddResidualBlock

​ 添加残差块添加到problem中,有多种形式,主要为:

  ResidualBlockId AddResidualBlock(
      CostFunction* cost_function,
      LossFunction* loss_function,
      const std::vector<double*>& parameter_blocks);

代价函数:包含了参数模块的维度信息,内部使用仿函数定义误差函数的计算方式.

损失函数:处理参数中有野值的情况.

参数模块:待优化的参数(隐式传递参数)

ps:
这里的parameter_blocks的参数块应该与costFunction的AddParameterBlock一一对应,在内部构建参数块的时候是依赖costFunction的parameter_block_sizes_的这个vector的,parameter_block_sizes_提供了每个参数的大小。

AddParameterBlock

​ 添加参数块(重复调用相同参数会被无视)

 void AddParameterBlock(double* values,
                        int size,
                        LocalParameterization* local_parameterization);

LocalParameterization类的作用是解决非线性优化中的过参数化问题。所谓过参数化,即待优化参数的实际自由度小于参数本身的自由度。例如在SLAM中,当采用四元数表示位姿时,由于四元数本身的约束(模长为1),实际的自由度为3而非4。此时,若直接传递四元数进行优化,冗余的维数会带来计算资源的浪费,需要使用Ceres预先定义的QuaternionParameterization对优化参数进行重构.
LocalParameterization见下面.

SetParameterBlockConstant

​ 设置参数块为不变的,优化过程中不改变该变量,Class ParameterBlock中有一个 is_constant_ 参数,设置为true.

SetParameterBlockVariable

​ 设置参数块为可变的,优化过程中优化的量,Class ParameterBlock中有一个 is_constant_ 参数,设置为false.

Evaluate

​ 该函数紧跟在参数赋值后,在给定的参数位置求解Problem,给出当前位置处的cost、梯度以及Jacobian矩阵.

class LocalParameterization

该类为虚基类,ceres定义几种类集成了该类,也可以自定义.

class CERES_EXPORT LocalParameterization {
 public:
  virtual ~LocalParameterization();
  virtual bool Plus(const double* x,
                    const double* delta,
                    double* x_plus_delta) const = 0;

  virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0;

  virtual bool MultiplyByJacobian(const double* x,
                                  const int num_rows,
                                  const double* global_matrix,
                                  double* local_matrix) const;

  virtual int GlobalSize() const = 0;

  virtual int LocalSize() const = 0;
};


若是自定义的函数,上述成员函数中,需要我们改写的是:

GlobalSize() 本身的参数的个数(例如QuaternionParameterization ,GlobalSize() = 4,四元数本身上是四维的变量)

LocalSize() 实际优化的参数个数(例如QuaternionParameterization ,LocalSize() = 3,ceres采用旋转矢量就行优化,维数为3)

Plus() ComputeJacobian() 这需要根据不同参数来定,比如q元素相加

Class CostFunction

CostFunction用来计算残差和雅克比矩阵,ceres提供不同类型的CostFunction,都是从这个类开始继承的.

class CostFunction {
 public:
  virtual bool Evaluate(double const* const* parameters,
                        double* residuals,
                        double** jacobians) = 0;
  const vector<int32>& parameter_block_sizes();
  int num_residuals() const;

 protected:
  vector<int32>* mutable_parameter_block_sizes();
  void set_num_residuals(int num_residuals);
 private:
  std::vector<int32> parameter_block_sizes_;
  int num_residuals_;
};

Evaluate()函数要根据参数计算残差和雅克比.

Class SizedCostFunction

Class SizedCostFunction继承了Class CostFunction

当在编译前已知优化参数的大小,残差的大小的时候可以使用这个类,只需要重写一下Evaluate函数就好了

template<int kNumResiduals,
         int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
         int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
class SizedCostFunction : public CostFunction {
 public:
  virtual bool Evaluate(double const* const* parameters,
                        double* residuals,
                        double** jacobians) const = 0;
};

class AutoDiffCostFunction

自动求导的代价函数,继承了Class SizedCostFunction.

template <typename CostFunctor,
       int kNumResiduals,  // Number of residuals, or ceres::DYNAMIC.
       int N0,       // Number of parameters in block 0.
       int N1 = 0,   // Number of parameters in block 1.
       int N2 = 0,   // Number of parameters in block 2.
       int N3 = 0,   // Number of parameters in block 3.
       int N4 = 0,   // Number of parameters in block 4.
       int N5 = 0,   // Number of parameters in block 5.
       int N6 = 0,   // Number of parameters in block 6.
       int N7 = 0,   // Number of parameters in block 7.
       int N8 = 0,   // Number of parameters in block 8.
       int N9 = 0>   // Number of parameters in block 9.
class AutoDiffCostFunction : public
SizedCostFunction<kNumResiduals, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9> {
 public:
  explicit AutoDiffCostFunction(CostFunctor* functor);
  // Ignore the template parameter kNumResiduals and use
  // num_residuals instead.
  AutoDiffCostFunction(CostFunctor* functor, int num_residuals);
};

需要自定义一个costfunction类作为类模板的CostFunctor,重写一下operator()函数,要用类模板.

使用说明:

CostFunction* cost_function
    = new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
        new MyScalarCostFunctor(1.0));              ^  ^  ^
                                                    |  |  |
                        Dimension of residual ------+  |  |
                        Dimension of x ----------------+  |
                        Dimension of y -------------------+

Class DynamicAutoDiffCostFunction

Class AutoDiffCostFunction适用于事先知道参数的大小和数量,且不超过10个参数块,但在许多问题上不适用,比如曲线拟合,所以需要Class DynamicAutoDiffCostFunction.

Class DynamicAutoDiffCostFunction继承了虚基类Class DynamicCostFunction,该类是从Class CostFunction继承过来的.

使用时需要定义一个类作为类模板CostFunctor,重写一下operator()函数

struct MyCostFunctor {
  template<typename T>
  bool operator()(T const* const* parameters, T* residuals) const {
  }
}

之后还要调用AddParameterBlock()和SetNumResiduals()函数来动态添加参数块.

Class NumericDiffCostFunction

在有些时候无法编写出数值上的CostFunctor,比如需要调用库函数的时候,此时就需要Class NumericDiffCostFunction.

像auto diff是通过公式自动求导,而NumericDiff则是通过数值差来求导,有三种求导方式:

FORWARD 使用该公式来求导,速度最快但经度最低
f ′ ( x ) = f ( x + h ) − f ( x ) h f′(x)=\frac {f(x+h)−f(x)}h f(x)=hf(x+h)f(x)
CENTRAL 默认使用的方法
f ′ ( x ) = f ( x + h ) − f ( x − h ) 2 h f′(x)=\frac {f(x+h)−f(x-h)}{2h} f(x)=2hf(x+h)f(xh)
RIDDERS 这种方法是在不同尺度执行中心差来估计导数,是种自适应的方法,经度很高,但是会造成计算的成本.

Ceres库是一个开源的C++库,用于解决非线性最小二乘问题。它提供了一套先进的优化算法和工具,可用于求解各种各样的优化问题,比如相机标定、图像配准、立体视觉、SLAM等。 首先,为了开始使用Ceres库,我们需要在计算机上安装它。对于Windows用户,可以从Ceres的官方网站上下载预编译好的二进制文件,并将其添加到系统环境变量。对于Linux或Mac用户,可以通过命令行安装,并使用包管理器(如apt-get或brew)来安装Ceres库。 安装完成后,我们可以在代码包含Ceres库的头文件,并链接相应的库文件,以便在程序使用Ceres的功能。接下来,我们需要定义一个优化问题,并添加待优化的参数、残差函数和约束条件。 在Ceres,我们可以通过定义一个继承自ceres::CostFunction的来表示残差函数。同时,在优化问题可以使用ceres::Problem来添加和管理这些残差函数。通过构建、配置和解决这个问题,Ceres库可以自动寻找最优的参数值,使得所有残差函数的总和最小。 值得一提的是,在使用Ceres库时,我们需要定义自己的残差函数,并提供优化问题的初始参数。同时,也可以选择合适的优化算法和迭代次数,以及监控优化过程的输出信息。 总之,Ceres库是一个功能强大的开源优化库,使用它可以很方便地解决非线性最小二乘问题。通过正确安装和使用Ceres库,我们可以有效地求解各种优化问题,并获得最佳的优化结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值