아래 식을 만족하는 curve 찾기 (curve fitting)
목적함수
// residual
struct CURVE_FITTING_COST {
CURVE_FITTING_COST(double x, double y) : _x(x), _y(y) {}
// implement operator () to compute the error
template<typename T>
bool operator()(
const T *const abc, // the estimated variables, 3D vector
T *residual) const {
residual[0] = T(_y) - ceres::exp(abc[0] * T(_x) * T(_x) + abc[1] * T(_x) + abc[2]); // y-exp(ax^2+bx+c)
return true;
}
const double _x, _y; // x,y data
};
parameter block 정의
→ 일반적으로 1차원 벡터지만 quaternion이나 Lie 대수로 정의 가능
double abc[3] = {ae, be, ce}; // 최적화 변수
residual 값을 계산하는 residual block 정의
→ residual의 제곱 합을 ceres가 계산해줌
ceres::Problem problem;
for (int i = 0; i < N; i++) {
problem.AddResidualBlock( // add i−th residual into the problem
// use auto−diff, template params: residual type, output dimension, input dimension
// should be same as the struct written before
new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 3>(
new CURVE_FITTING_COST(x_data[i], y_data[i])
),
nullptr, // kernel function, don't use here
abc // estimated variables
);
}
residual block에서 Jacobian 계산정의
→ ‘automatic derivative function’ 사용 또는 직접 계산 프로세스를 정의
// error의 차원: 1
// 최적화 변수 개수: 3
new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 3>(
new CURVE_FITTING_COST(x_data[i], y_data[i])
)
parameter block과 residual block을 ceres problem object에 넣어 Solve function 수행
// set the solver options
ceres::Solver::Options options; // actually there are lots of params can be adjusted
options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY; // use cholesky to solve the normal equation
// solve problem
ceres::Solver::Summary summary; // optimization information
ceres::Solve(options, &problem, &summary); // do optimization!