#include <cstdio>
#include <vector>
#include "ceres/ceres.h"
#include "gflags/gflags.h"
#include "glog/logging.h"
using ceres::AutoDiffCostFunction;
using ceres::CauchyLoss;
using ceres::CostFunction;
using ceres::LossFunction;
using ceres::Problem;
using ceres::Solve;
using ceres::Solver;
DEFINE_double(robust_threshold, 0.0, "Robust loss parameter. Set to 0 for "
"normal squared error (no robustification).");
class DistanceFromCircleCost {
public:
DistanceFromCircleCost(double xx, double yy) : xx_(xx), yy_(yy) {}
template <typename T> bool operator()(const T* const x,
const T* const y,
const T* const m, T* residual) const {
T r = *m * *m;
T xp = xx_ - *x;
T yp = yy_ - *y;
residual[0] = r*r - xp*xp - yp*yp;
return true;
}
private:
double xx_, yy_;
};
int main(int argc, char** argv) {
CERES_GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
double x, y, r;
if (scanf("%lg %lg %lg", &x, &y, &r) != 3) {
fprintf(stderr, "Couldn't read first line.\n");
return 1;
}
fprintf(stderr, "Got x, y, r %lg, %lg, %lg\n", x, y, r);
double initial_x = x;
double initial_y = y;
double initial_r = r;
double m = sqrt(r);
Problem problem;
LossFunction* loss = NULL;
if (FLAGS_robust_threshold) {
loss = new CauchyLoss(FLAGS_robust_threshold);
}
double xx, yy;
int num_points = 0;
while (scanf("%lf %lf\n", &xx, &yy) == 2) {
CostFunction *cost =
new AutoDiffCostFunction<DistanceFromCircleCost, 1, 1, 1, 1>(
new DistanceFromCircleCost(xx, yy));
problem.AddResidualBlock(cost, loss, &x, &y, &m);
num_points++;
}
std::cout << "Got " << num_points << " points.\n";
Solver::Options options;
options.max_num_iterations = 500;
options.linear_solver_type = ceres::DENSE_QR;
Solver::Summary summary;
Solve(options, &problem, &summary);
r = m * m;
std::cout << summary.BriefReport() << "\n";
std::cout << "x : " << initial_x << " -> " << x << "\n";
std::cout << "y : " << initial_y << " -> " << y << "\n";
std::cout << "r : " << initial_r << " -> " << r << "\n";
return 0;
}