-
Notifications
You must be signed in to change notification settings - Fork 44
/
baproblem.hpp
142 lines (113 loc) · 4.1 KB
/
baproblem.hpp
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#ifndef BAPROBLEM_HPP_
#define BAPROBLEM_HPP_
#include "parametersse3.hpp"
class Sample
{
public:
static int uniform(int from, int to);
static double uniform();
static double gaussian(double sigma);
};
/// PoseBlockSize can only be
/// 7 (quaternion + translation vector) or
/// 6 (rotation vector + translation vector)
template <int PoseBlockSize>
class BAProblem
{
public:
BAProblem(int pose_num_, int point_num_, double pix_noise_, bool useOrdering = false);
void solve(ceres::Solver::Options &opt, ceres::Solver::Summary* sum);
ceres::Problem problem;
ceres::ParameterBlockOrdering* ordering = NULL;
protected:
PosePointParametersBlock<PoseBlockSize> states;
PosePointParametersBlock<PoseBlockSize> true_states;
};
template<int PoseBlockSize>
BAProblem<PoseBlockSize>::BAProblem(int pose_num_, int point_num_, double pix_noise_, bool useOrdering)
{
if(useOrdering)
ordering = new ceres::ParameterBlockOrdering;
int pose_num = pose_num_;
int point_num = point_num_;
double PIXEL_NOISE = pix_noise_;
states.create(pose_num, point_num);
true_states.create(pose_num, point_num);
for (int i = 0; i < point_num; ++i)
{
Eigen::Map<Vector3d> true_pt(true_states.point(i));
true_pt = Vector3d((Sample::uniform() - 0.5) * 3,
Sample::uniform() - 0.5,
Sample::uniform() + 3);
}
double focal_length = 1000.;
double cx = 320.;
double cy = 240.;
CameraParameters cam(focal_length, cx, cy);
for (int i = 0; i < pose_num; ++i)
{
Vector3d trans(i * 0.04 - 1., 0, 0);
Eigen::Quaterniond q;
q.setIdentity();
true_states.setPose(i, q, trans);
states.setPose(i, q, trans);
problem.AddParameterBlock(states.pose(i), PoseBlockSize, new PoseSE3Parameterization<PoseBlockSize>());
if(i < 2)
{
problem.SetParameterBlockConstant(states.pose(i));
}
}
for (int i = 0; i < point_num; ++i)
{
Eigen::Map<Vector3d> true_point_i(true_states.point(i));
Eigen::Map<Vector3d> noise_point_i(states.point(i));
noise_point_i = true_point_i + Vector3d(Sample::gaussian(1),
Sample::gaussian(1),
Sample::gaussian(1));
Vector2d z;
SE3 true_pose_se3;
int num_obs = 0;
for (int j = 0; j < pose_num; ++j)
{
true_states.getPose(j, true_pose_se3.rotation(), true_pose_se3.translation());
Vector3d point_cam = true_pose_se3.map(true_point_i);
z = cam.cam_map(point_cam);
if (z[0] >= 0 && z[1] >= 0 && z[0] < 640 && z[1] < 480)
{
++num_obs;
}
}
if (num_obs >= 2)
{
problem.AddParameterBlock(states.point(i), 3);
if(useOrdering)
ordering->AddElementToGroup(states.point(i), 0);
for (int j = 0; j < pose_num; ++j)
{
true_states.getPose(j, true_pose_se3.rotation(), true_pose_se3.translation());
Vector3d point_cam = true_pose_se3.map(true_point_i);
z = cam.cam_map(point_cam);
if (z[0] >= 0 && z[1] >= 0 && z[0] < 640 && z[1] < 480)
{
z += Vector2d(Sample::gaussian(PIXEL_NOISE),
Sample::gaussian(PIXEL_NOISE));
ceres::CostFunction* costFunc = new ReprojectionErrorSE3XYZ<PoseBlockSize>(focal_length, cx, cy, z[0], z[1]);
problem.AddResidualBlock(costFunc, NULL, states.pose(j), states.point(i));
}
}
}
}
if(useOrdering)
for (int i = 0; i < pose_num; ++i)
{
ordering->AddElementToGroup(states.pose(i), 1);
}
}
template<int PoseBlockSize>
void BAProblem<PoseBlockSize>::solve(ceres::Solver::Options& opt, ceres::Solver::Summary *sum)
{
if(ordering != NULL)
opt.linear_solver_ordering.reset(ordering);
ceres::Solve(opt, &problem, sum);
}
#endif