Skip to content

Commit 70f058f

Browse files
Merge pull request #919 from RainerKuemmerle/pymem-merge
Pymem merge
2 parents 093049d + 6830911 commit 70f058f

4 files changed

Lines changed: 117 additions & 33 deletions

File tree

g2o/types/icp/edge_gicp.cpp

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,44 @@
2828

2929
#include <Eigen/Geometry>
3030

31+
#include "g2o/core/eigen_types.h"
32+
3133
namespace g2o {
3234

35+
namespace {
36+
constexpr double kYSquaredBnd{0.1};
37+
38+
void makeRot(Matrix3& R, const Vector3& normal) {
39+
Vector3 y(0., 1., 0.);
40+
R.row(2) = normal;
41+
y = y - normal(1) * normal;
42+
const double ysquarednorm = y.squaredNorm();
43+
if (ysquarednorm >= kYSquaredBnd) {
44+
y /= std::sqrt(ysquarednorm);
45+
R.row(1) = y;
46+
R.row(0) = normal.cross(R.row(1));
47+
} else {
48+
Vector3 x(-1., 0., 0.);
49+
x = x + normal(0) * normal;
50+
x.normalize();
51+
R.row(0) = x;
52+
R.row(1) = -normal.cross(R.row(0));
53+
}
54+
}
55+
56+
Matrix3 prec(double e, const Matrix3& R) {
57+
Matrix3 prec_mat;
58+
prec_mat << e, 0, 0, 0, e, 0, 0, 0, 1;
59+
return R.transpose() * prec_mat * R;
60+
}
61+
62+
Matrix3 cov(double e, const Matrix3& R) {
63+
Matrix3 cov_mat;
64+
cov_mat << 1, 0, 0, 0, 1, 0, 0, 0, e;
65+
return R.transpose() * cov_mat * R;
66+
}
67+
} // namespace
68+
3369
EdgeGICP::EdgeGICP() {
3470
pos0.setZero();
3571
pos1.setZero();
@@ -40,55 +76,28 @@ EdgeGICP::EdgeGICP() {
4076
R1.setIdentity();
4177
}
4278

43-
void EdgeGICP::makeRot0() {
44-
Vector3 y;
45-
y << 0, 1, 0;
46-
R0.row(2) = normal0;
47-
y = y - normal0(1) * normal0;
48-
y.normalize(); // need to check if y is close to 0
49-
R0.row(1) = y;
50-
R0.row(0) = normal0.cross(R0.row(1));
51-
// cout << normal.transpose() << endl;
52-
// cout << R0 << endl << endl;
53-
// cout << R0*R0.transpose() << endl << endl;
54-
}
79+
void EdgeGICP::makeRot0() { makeRot(R0, normal0); }
5580

56-
void EdgeGICP::makeRot1() {
57-
Vector3 y;
58-
y << 0, 1, 0;
59-
R1.row(2) = normal1;
60-
y = y - normal1(1) * normal1;
61-
y.normalize(); // need to check if y is close to 0
62-
R1.row(1) = y;
63-
R1.row(0) = normal1.cross(R1.row(1));
64-
}
81+
void EdgeGICP::makeRot1() { makeRot(R1, normal1); }
6582

6683
Matrix3 EdgeGICP::prec0(double e) {
6784
makeRot0();
68-
Matrix3 prec;
69-
prec << e, 0, 0, 0, e, 0, 0, 0, 1;
70-
return R0.transpose() * prec * R0;
85+
return prec(e, R0);
7186
}
7287

7388
Matrix3 EdgeGICP::prec1(double e) {
7489
makeRot1();
75-
Matrix3 prec;
76-
prec << e, 0, 0, 0, e, 0, 0, 0, 1;
77-
return R1.transpose() * prec * R1;
90+
return prec(e, R1);
7891
}
7992

8093
Matrix3 EdgeGICP::cov0(double e) {
8194
makeRot0();
82-
Matrix3 cov;
83-
cov << 1, 0, 0, 0, 1, 0, 0, 0, e;
84-
return R0.transpose() * cov * R0;
95+
return cov(e, R0);
8596
}
8697

8798
Matrix3 EdgeGICP::cov1(double e) {
8899
makeRot1();
89-
Matrix3 cov;
90-
cov << 1, 0, 0, 0, 1, 0, 0, 0, e;
91-
return R1.transpose() * cov * R1;
100+
return cov(e, R1);
92101
}
93102

94103
} // namespace g2o

unit_test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ add_subdirectory(slam3d)
3838
add_subdirectory(sba)
3939
add_subdirectory(sim3)
4040
add_subdirectory(solver)
41+
add_subdirectory(icp)
4142

4243
if (TARGET simulator_lib)
4344
add_subdirectory(simulator)

unit_test/icp/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
add_executable(unittest_icp
2+
icp_rotation.cpp
3+
)
4+
target_link_libraries(unittest_icp types_icp)
5+
create_test(unittest_icp)

unit_test/icp/icp_rotation.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// g2o - General Graph Optimization
2+
// Copyright (C) 2014 R. Kuemmerle, G. Grisetti, W. Burgard
3+
// All rights reserved.
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// modification, are permitted provided that the following conditions are
7+
// met:
8+
//
9+
// * Redistributions of source code must retain the above copyright notice,
10+
// this list of conditions and the following disclaimer.
11+
// * Redistributions in binary form must reproduce the above copyright
12+
// notice, this list of conditions and the following disclaimer in the
13+
// documentation and/or other materials provided with the distribution.
14+
//
15+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16+
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17+
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18+
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19+
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21+
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22+
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23+
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24+
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
27+
#include "g2o/types/icp/types_icp.h"
28+
#include "gtest/gtest.h"
29+
30+
using namespace g2o;
31+
32+
void checkRotationMatrix(const Matrix3& R) {
33+
constexpr double tol = 1e-14;
34+
// check norms of basis vectors
35+
EXPECT_NEAR(R.row(0).norm(), 1, tol);
36+
EXPECT_NEAR(R.row(1).norm(), 1, tol);
37+
EXPECT_NEAR(R.row(2).norm(), 1, tol);
38+
// check orthogonality
39+
EXPECT_NEAR(R.row(0).dot(R.row(1)), 0, tol);
40+
EXPECT_NEAR(R.row(1).dot(R.row(2)), 0, tol);
41+
EXPECT_NEAR(R.row(2).dot(R.row(0)), 0, tol);
42+
// check that basis is left-handed
43+
EXPECT_NEAR(R.determinant(), -1.0, tol);
44+
}
45+
46+
/*
47+
* ROTATION MATRIX Tests
48+
*/
49+
TEST(IcpRotation, RotationMatrix) {
50+
constexpr size_t thetaPoints = 100;
51+
constexpr size_t phiPoints = 100;
52+
EdgeGICP edge;
53+
for (size_t n = 0; n < thetaPoints; n++) {
54+
const double theta = M_PI * n / thetaPoints;
55+
for (size_t k = 0; k < phiPoints; k++) {
56+
const double phi = 2.0L * M_PI * k / phiPoints;
57+
const Vector3 normal(std::sin(theta) * std::cos(phi), std::cos(theta),
58+
std::sin(theta) * std::sin(phi));
59+
edge.normal0 = normal;
60+
edge.normal1 = normal;
61+
62+
edge.makeRot0();
63+
edge.makeRot1();
64+
65+
checkRotationMatrix(edge.R0);
66+
checkRotationMatrix(edge.R1);
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)