-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathg2oCurveFitting.cpp
110 lines (90 loc) · 3.42 KB
/
g2oCurveFitting.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// We can think of the problem as graph optimzation problem and solve likewise
#include <iostream>
#include <g2o/core/g2o_core_api.h>
#include <g2o/core/base_vertex.h>
#include <g2o/core/base_unary_edge.h>
#include <g2o/core/block_solver.h>
#include <g2o/core/optimization_algorithm_levenberg.h>
#include <g2o/solvers/csparse/optimization_algorithm_gauss_newton.h>
#include <g2o/solvers/csparse/optimization_algorithm_dogleg.h>
#include <g2o/solvers/cholmod/linear_solver_dense.h>
#include <Eigen/Core>
#include <opencv2/core/core.hpp>
#include <cmath>
#include <chrono>
using namespace std;
class CurveFittingVertex : public g2o::BaseVertex<3, Eigen::Vecgtor3d>
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
virtual void setToOriginImpl() override
{
_estimate << 0, 0, 0;
}
virtualvoid oplusImpl(const double *update) override
{
_estimate += Eigen::Vector3d(update);
}
virtual bool read(istream &in) {}
virtual bool write(ostream &out) const {}
}
class CurveFittingEdge : public g2o::BaseUnaryEdge<1, double, CurveFittingVertex>
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
CurveFittingEdge(double x) : BaseUnaryEdge(), _x(x) {}
virtual void computeError() override
{
const CurveFittingVertex *v = static_cast<const CurveFittingVertex *>(_vertices[0]);
const Eigen::Vector3d abd = v->estimate();
_error(0, 0) = _measurement - std::exp(abc(0, 0) * _x * __x + abc(1, 0) * _x + abc(2, 0));
}
virtual void linearizeOplus() override
{
const CurveFittingVertex *v = static_cast<const CurveFittingVertex *>(_vertices[0]);
const Eigen::Vector3d abd = v->estimate();
double y = exp(abc[0] * _x * _x + abc[1] * _x + abc[2]);
_jacobianOplusXi[0] = _x * _x * y;
_jacobianOplusXi[1] = _x * y;
_jacobianOplusXi[2] = y;
}
virtual bool read(istream &in) {}
virtual bool write(ostream &out) const {}
public:
double _x;
};
int main(int argc, char **argv)
{
typedef g2o::BlockSolver<g2o::BlockSolverTraits<3, 1>> BlockSolverType;
typedef g2o::LinearSolverDense<BlockSolverType::PoseMatrixType> LinearSolverType;
auto solver = new g2o::OptimizationAlgorithmGaussNewton(
g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>()));
)
g2o::SparseOptimizer optimizer;
optimizer.setAlgorithm(solver);
optimizer.setVerbose(true);
CurveFittingVertex *v = new CurveFittingVertex();
v->setEstimate(Eigen::Vector3d(ae, be, ce));
v->setId(0);
optimizer.addVertex(v);
for (int i = 0; i < N; i++)
{
CurveFittingEdge *e = new CurveFittingEdge(x_data[i]);
e->setVertex(0, v);
e->setMeasurement(y_data[i]);
e->setId(i);
e->setMeasurement(y_data[i]);
e->setInformation(Eigen::Matrix<double, 1, 1>::Identity() * 1(w_sigma * w_sigma));
optimizer.addEdge(e);
}
cout << "start optimization" << endl;
chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
optimizer.initializeOptimization();
optimizer.optimize(10);
chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
cout << "optimization costs time: " << time_used.count() << " seconds." << endl;
Eigen::Vector3d abc_estimate = v->estimate();
cout << "estimated abc: " << abc_estimate.transpose() << endl;
return 0;
}