59int main(
int argc,
const char* argv[]) {
62 cout <<
"Please type: " << endl;
63 cout <<
"ba_demo [PIXEL_NOISE] [OUTLIER RATIO] [ROBUST_KERNEL] "
64 "[STRUCTURE_ONLY] [DENSE]"
67 cout <<
"PIXEL_NOISE: noise in image space (E.g.: 1)" << endl;
68 cout <<
"OUTLIER_RATIO: probability of spuroius observation (default: 0.0)"
70 cout <<
"ROBUST_KERNEL: use robust kernel (0 or 1; default: 0==false)"
72 cout <<
"STRUCTURE_ONLY: performed structure-only BA to get better point "
73 "initializations (0 or 1; default: 0==false)"
75 cout <<
"DENSE: Use dense solver (0 or 1; default: 0==false)" << endl;
77 cout <<
"Note, if OUTLIER_RATIO is above 0, ROBUST_KERNEL should be set to "
84 double PIXEL_NOISE = atof(argv[1]);
86 double OUTLIER_RATIO = 0.0;
89 OUTLIER_RATIO = atof(argv[2]);
92 bool ROBUST_KERNEL =
false;
94 ROBUST_KERNEL = atoi(argv[3]) != 0;
96 bool STRUCTURE_ONLY =
false;
98 STRUCTURE_ONLY = atoi(argv[4]) != 0;
103 DENSE = atoi(argv[5]) != 0;
106 cout <<
"PIXEL_NOISE: " << PIXEL_NOISE << endl;
107 cout <<
"OUTLIER_RATIO: " << OUTLIER_RATIO << endl;
108 cout <<
"ROBUST_KERNEL: " << ROBUST_KERNEL << endl;
109 cout <<
"STRUCTURE_ONLY: " << STRUCTURE_ONLY << endl;
110 cout <<
"DENSE: " << DENSE << endl;
114 std::unique_ptr<g2o::BlockSolver_6_3::LinearSolverType> linearSolver;
116 linearSolver = std::make_unique<
118 cerr <<
"Using DENSE" << endl;
120#ifdef G2O_HAVE_CHOLMOD
121 cerr <<
"Using CHOLMOD" << endl;
122 linearSolver = std::make_unique<
125 linearSolver = std::make_unique<
127 cerr <<
"Using CSPARSE" << endl;
133 std::make_unique<g2o::BlockSolver_6_3>(std::move(linearSolver)));
138 vector<Vector3d> true_points;
139 for (
size_t i = 0; i < 500; ++i) {
140 true_points.push_back(
146 Vector2d focal_length(500, 500);
147 Vector2d principal_point(320, 240);
148 double baseline = 0.075;
150 vector<Eigen::Isometry3d, aligned_allocator<Eigen::Isometry3d>> true_poses;
154 principal_point[1], baseline);
158 for (
size_t i = 0; i < 5; ++i) {
159 Vector3d trans(i * 0.04 - 1., 0, 0);
161 Eigen::Quaterniond q;
163 Eigen::Isometry3d pose;
165 pose.translation() = trans;
169 v_se3->
setId(vertex_id);
176 true_poses.push_back(pose);
180 int point_id = vertex_id;
181 double sum_diff2 = 0;
184 unordered_map<int, int> pointid_2_trueid;
185 unordered_set<int> inliers;
188 for (
size_t i = 0; i < true_points.size(); ++i) {
191 v_p->
setId(point_id);
200 for (
size_t j = 0; j < true_poses.size(); ++j) {
203 ->mapPoint(z, true_points.at(i));
205 if (z[0] >= 0 && z[1] >= 0 && z[0] < 640 && z[1] < 480) {
214 for (
size_t j = 0; j < true_poses.size(); ++j) {
217 ->mapPoint(z, true_points.at(i));
219 if (z[0] >= 0 && z[1] >= 0 && z[0] < 640 && z[1] < 480) {
221 if (sam < OUTLIER_RATIO) {
238 optimizer.
vertices().find(j)->second);
254 inliers.insert(point_id);
255 Vector3d diff = v_p->
estimate() - true_points[i];
257 sum_diff2 += diff.dot(diff);
263 pointid_2_trueid.insert(make_pair(point_id, i));
274 if (STRUCTURE_ONLY) {
275 cout <<
"Performing structure-only BA:" << endl;
278 for (g2o::OptimizableGraph::VertexIDMap::const_iterator it =
280 it != optimizer.
vertices().end(); ++it) {
283 if (v->
dimension() == 3) points.push_back(v);
286 structure_only_ba.
calc(points, 10);
290 cout <<
"Performing full BA:" << endl;
294 cout <<
"Point error before optimisation (inliers only): "
295 << sqrt(sum_diff2 / inliers.size()) << endl;
299 for (unordered_map<int, int>::iterator it = pointid_2_trueid.begin();
300 it != pointid_2_trueid.end(); ++it) {
301 g2o::HyperGraph::VertexIDMap::iterator v_it =
302 optimizer.
vertices().find(it->first);
304 if (v_it == optimizer.
vertices().end()) {
305 cerr <<
"Vertex " << it->first <<
" not in graph!" << endl;
312 cerr <<
"Vertex " << it->first <<
"is not a PointXYZ!" << endl;
316 Vector3d diff = v_p->
estimate() - true_points[it->second];
318 if (inliers.find(it->first) == inliers.end())
continue;
320 sum_diff2 += diff.dot(diff);
323 cout <<
"Point error after optimisation (inliers only): "
324 << sqrt(sum_diff2 / inliers.size()) << endl;