@@ -9,6 +9,7 @@ using IndexType = int64_t;
9
9
using EigenMatrix = Eigen::MatrixXd;
10
10
using EigenVector = Eigen::VectorXd;
11
11
12
+ #include " common/io.h"
12
13
#include " common/kdtree.h"
13
14
#include " common/debug.h"
14
15
#include " svd.h"
@@ -29,18 +30,14 @@ EigenMatrix rodrigues(const EigenVector &w, const double theta) {
29
30
const double wy = w (1 );
30
31
const double wz = w (2 );
31
32
EigenMatrix K (3 , 3 );
32
- K << 0.0 , -wz, wy,
33
- wz, 0.0 , -wx,
34
- -wy, wx, 0.0 ;
33
+ K << 0.0 , -wz, wy, wz, 0.0 , -wx, -wy, wx, 0.0 ;
35
34
36
35
EigenMatrix I = EigenMatrix::Identity (3 , 3 );
37
36
return I + K * s + (K * K) * (1.0 - c);
38
37
}
39
38
40
39
// ! single point to point ICP step
41
- void point2pointICP_step (const std::vector<Vec3> &target,
42
- const std::vector<Vec3> &source,
43
- EigenMatrix *rotMat,
40
+ void point2pointICP_step (const std::vector<Vec3> &target, const std::vector<Vec3> &source, EigenMatrix *rotMat,
44
41
EigenVector *trans) {
45
42
// Construct Kd-tree to find closest points
46
43
KDTree<Vec3> tree;
@@ -49,6 +46,10 @@ void point2pointICP_step(const std::vector<Vec3> &target,
49
46
// {{ NOT_IMPL_ERROR();
50
47
51
48
// Match closest point pairs
49
+ // Hint:
50
+ // Construct here that two matrices X and P,
51
+ // whose elements are positions of source vertices (X),
52
+ // and those for closest points of the sources (P)
52
53
const int nPoints = (int )source.size ();
53
54
EigenMatrix X (nPoints, 3 );
54
55
EigenMatrix P (nPoints, 3 );
@@ -60,12 +61,18 @@ void point2pointICP_step(const std::vector<Vec3> &target,
60
61
}
61
62
62
63
// Subtract xMean, pMean from X, P
64
+ // Hint:
65
+ // Row-wise or column-wise mean (also sum, max, min etc.) of Eigen matrices
66
+ // can be easily calculate using "rowwise()" or "colwise()".
63
67
const EigenVector xMean = X.colwise ().mean ();
64
68
const EigenVector pMean = P.colwise ().mean ();
65
69
X.rowwise () -= xMean.transpose ();
66
70
P.rowwise () -= pMean.transpose ();
67
71
68
72
// Solve with SVD to obtain R
73
+ // Hint:
74
+ // An SVD method "eigenSVD" is already given in "svd.h".
75
+ // See its arguments carefully when using it.
69
76
const EigenMatrix M = P.transpose () * X;
70
77
EigenMatrix U, V;
71
78
EigenVector sigma;
@@ -77,18 +84,19 @@ void point2pointICP_step(const std::vector<Vec3> &target,
77
84
diagH << 1.0 , 1.0 , detVU;
78
85
79
86
// Output
87
+ // Hint:
88
+ // Be careful that arguments for output matrices and vectors
89
+ // are represented as "pointers". Therefore, you should insert
90
+ // values for them with "asterisk" like "*lhs = rhs".
80
91
*rotMat = U * diagH.asDiagonal () * V.transpose ();
81
92
*trans = pMean - (*rotMat) * xMean;
82
93
83
94
// }}
84
95
}
85
96
86
97
// ! single point to plane ICP step
87
- void point2planeICP_step (const std::vector<Vec3> &target,
88
- const std::vector<Vec3> &targetNorm,
89
- const std::vector<Vec3> &source,
90
- Eigen::MatrixXd *rotMat,
91
- Eigen::VectorXd *trans) {
98
+ void point2planeICP_step (const std::vector<Vec3> &target, const std::vector<Vec3> &targetNorm,
99
+ const std::vector<Vec3> &source, Eigen::MatrixXd *rotMat, Eigen::VectorXd *trans) {
92
100
// Construct Kd-tree to find closest points
93
101
std::vector<Point > points;
94
102
for (int i = 0 ; i < (int )target.size (); i++) {
@@ -101,7 +109,10 @@ void point2planeICP_step(const std::vector<Vec3> &target,
101
109
// {{ NOT_IMPL_ERROR();
102
110
103
111
// Construct linear system
104
- const int nPoints = (int ) source.size ();
112
+ // Hint:
113
+ // prepare matrix A and vector b
114
+ // A is 6x6 matrix, and b is 6-D vector
115
+ const int nPoints = (int )source.size ();
105
116
EigenMatrix A (6 , 6 );
106
117
EigenVector b (6 );
107
118
A.setZero ();
@@ -119,16 +130,25 @@ void point2planeICP_step(const std::vector<Vec3> &target,
119
130
}
120
131
121
132
// Solve
133
+ // Hint:
134
+ // Use "Eigen::PartialPivLU" to solve the system
122
135
Eigen::PartialPivLU<EigenMatrix> lu (A);
123
136
EigenVector u = lu.solve (b);
124
137
125
138
// Substitute to instances a, t
139
+ // Hint:
140
+ // Eigen matrices and vectors can be initialized
141
+ // with its elements by "<<" operator.
126
142
EigenVector a (3 );
127
143
a << u (0 ), u (1 ), u (2 );
128
144
EigenVector t (3 );
129
145
t << u (3 ), u (4 ), u (5 );
130
146
131
147
// Reproduce rotation matrix
148
+ // Hint:
149
+ // Remember that vector "a" is the multiple of
150
+ // the direction of rotation axis and
151
+ // the degree of rotation angle.
132
152
const double theta = a.norm ();
133
153
const EigenVector w = a / theta;
134
154
*rotMat = rodrigues (w, theta);
@@ -137,29 +157,23 @@ void point2planeICP_step(const std::vector<Vec3> &target,
137
157
// }}
138
158
}
139
159
140
- void rigidICP (const std::vector<Vec3> &target,
141
- const std::vector<Vec3> &targetNorm,
142
- std::vector<Vec3> &source,
143
- std::vector<Vec3> &sourceNorm,
144
- ICPMetric metric,
145
- int maxIters,
146
- double tolerance,
147
- bool verbose) {
160
+ void rigidICP (const std::vector<Vec3> &target, const std::vector<Vec3> &targetNorm, std::vector<Vec3> &source,
161
+ std::vector<Vec3> &sourceNorm, ICPMetric metric, int maxIters, double tolerance, bool verbose) {
148
162
// Point-to-point ICP
149
163
for (int it = 0 ; it < maxIters; it++) {
150
164
Eigen::MatrixXd R (3 , 3 );
151
165
Eigen::VectorXd t (3 );
152
166
switch (metric) {
153
- case ICPMetric::Point2Point:
154
- point2pointICP_step (target, source, &R, &t);
155
- break ;
167
+ case ICPMetric::Point2Point:
168
+ point2pointICP_step (target, source, &R, &t);
169
+ break ;
156
170
157
- case ICPMetric::Point2Plane:
158
- point2planeICP_step (target, targetNorm, source, &R, &t);
159
- break ;
171
+ case ICPMetric::Point2Plane:
172
+ point2planeICP_step (target, targetNorm, source, &R, &t);
173
+ break ;
160
174
161
- default :
162
- throw std::runtime_error (" Unknown ICP metric type!" );
175
+ default :
176
+ throw std::runtime_error (" Unknown ICP metric type!" );
163
177
}
164
178
165
179
// Apply rigid transformation
@@ -189,6 +203,10 @@ void rigidICP(const std::vector<Vec3> &target,
189
203
printf (" \n " );
190
204
}
191
205
206
+ char outfile[256 ];
207
+ sprintf (outfile, " intermediate_%03d.off" , it);
208
+ write_off (std::string (outfile), source, sourceNorm);
209
+
192
210
if (error < tolerance) {
193
211
break ;
194
212
}
0 commit comments