ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
generalized_absolute_pose_test.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #define TEST_NAME "base/generalized_absolute_pose"
33 #include "util/testing.h"
34 
35 #include <array>
36 
37 #include <Eigen/Core>
38 
39 #include "base/pose.h"
40 #include "base/projection.h"
43 #include "optim/ransac.h"
44 #include "util/random.h"
45 
46 using namespace colmap;
47 
49  SetPRNGSeed(0);
50 
51  std::vector<Eigen::Vector3d> points3D;
52  points3D.emplace_back(1, 1, 1);
53  points3D.emplace_back(0, 1, 1);
54  points3D.emplace_back(3, 1.0, 4);
55  points3D.emplace_back(3, 1.1, 4);
56  points3D.emplace_back(3, 1.2, 4);
57  points3D.emplace_back(3, 1.3, 4);
58  points3D.emplace_back(3, 1.4, 4);
59  points3D.emplace_back(2, 1, 7);
60 
61  auto points3D_faulty = points3D;
62  for (size_t i = 0; i < points3D.size(); ++i) {
63  points3D_faulty[i](0) = 20;
64  }
65 
66  for (double qx = 0; qx < 1; qx += 0.2) {
67  for (double tx = 0; tx < 1; tx += 0.1) {
68  const int kRefTform = 1;
69  const int kNumTforms = 3;
70 
71  const std::array<SimilarityTransform3, kNumTforms> orig_tforms = {{
72  SimilarityTransform3(1, Eigen::Vector4d(1, qx, 0, 0),
73  Eigen::Vector3d(tx, -0.1, 0)),
74  SimilarityTransform3(1, Eigen::Vector4d(1, qx, 0, 0),
75  Eigen::Vector3d(tx, 0, 0)),
76  SimilarityTransform3(1, Eigen::Vector4d(1, qx, 0, 0),
77  Eigen::Vector3d(tx, 0.1, 0)),
78  }};
79 
80  std::array<Eigen::Matrix3x4d, kNumTforms> rel_tforms;
81  for (size_t i = 0; i < kNumTforms; ++i) {
82  Eigen::Vector4d rel_qvec;
83  Eigen::Vector3d rel_tvec;
84  ComputeRelativePose(orig_tforms[kRefTform].Rotation(),
85  orig_tforms[kRefTform].Translation(),
86  orig_tforms[i].Rotation(),
87  orig_tforms[i].Translation(), &rel_qvec, &rel_tvec);
88  rel_tforms[i] = ComposeProjectionMatrix(rel_qvec, rel_tvec);
89  }
90 
91  // Project points to camera coordinate system.
92  std::vector<GP3PEstimator::X_t> points2D;
93  for (size_t i = 0; i < points3D.size(); ++i) {
94  Eigen::Vector3d point3D_camera = points3D[i];
95  orig_tforms[i % kNumTforms].TransformPoint(&point3D_camera);
96  points2D.emplace_back();
97  points2D.back().rel_tform = rel_tforms[i % kNumTforms];
98  points2D.back().xy = point3D_camera.hnormalized();
99  }
100 
101  RANSACOptions options;
102  options.max_error = 1e-5;
103  RANSAC<GP3PEstimator> ransac(options);
104  const auto report = ransac.Estimate(points2D, points3D);
105 
106  BOOST_CHECK_EQUAL(report.success, true);
107 
108  // Test if correct transformation has been determined.
109  const double matrix_diff =
110  (orig_tforms[kRefTform].Matrix().topLeftCorner<3, 4>() - report.model)
111  .norm();
112  BOOST_CHECK(matrix_diff < 1e-2);
113 
114  // Test residuals of exact points.
115  std::vector<double> residuals;
116  ransac.estimator.Residuals(points2D, points3D, report.model, &residuals);
117  for (size_t i = 0; i < residuals.size(); ++i) {
118  BOOST_CHECK(residuals[i] < 1e-10);
119  }
120 
121  // Test residuals of faulty points.
122  ransac.estimator.Residuals(points2D, points3D_faulty, report.model,
123  &residuals);
124  for (size_t i = 0; i < residuals.size(); ++i) {
125  BOOST_CHECK(residuals[i] > 1e-10);
126  }
127  }
128  }
129 }
Estimator estimator
Definition: ransac.h:107
Report Estimate(const std::vector< typename Estimator::X_t > &X, const std::vector< typename Estimator::Y_t > &Y)
Definition: ransac.h:159
const double * e
BOOST_AUTO_TEST_CASE(Estimate)
void SetPRNGSeed(unsigned seed)
Definition: random.cc:40
void ComputeRelativePose(const Eigen::Vector4d &qvec1, const Eigen::Vector3d &tvec1, const Eigen::Vector4d &qvec2, const Eigen::Vector3d &tvec2, Eigen::Vector4d *qvec12, Eigen::Vector3d *tvec12)
Definition: pose.cc:173
Eigen::Matrix3x4d ComposeProjectionMatrix(const Eigen::Vector4d &qvec, const Eigen::Vector3d &tvec)
Definition: projection.cc:39