ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
generalized_relative_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_relative_pose"
33 #include "util/testing.h"
34 
35 #include <array>
36 
37 #include "base/pose.h"
38 #include "base/projection.h"
41 #include "optim/loransac.h"
42 #include "util/random.h"
43 
44 using namespace colmap;
45 
47  SetPRNGSeed(0);
48 
49  const size_t kNumPoints = 100;
50 
51  std::vector<Eigen::Vector3d> points3D;
52  for (size_t i = 0; i < kNumPoints; ++i) {
53  points3D.emplace_back(RandomReal<double>(-10, 10),
54  RandomReal<double>(-10, 10),
55  RandomReal<double>(-10, 10));
56  }
57 
58  for (double qx = 0; qx < 0.4; qx += 0.1) {
59  for (double tx = 0; tx < 0.5; tx += 0.1) {
60  const int kRefTform = 1;
61  const int kNumTforms = 3;
62 
63  const std::array<SimilarityTransform3, kNumTforms> orig_tforms = {{
64  SimilarityTransform3(1, Eigen::Vector4d(1, qx, 0, 0),
65  Eigen::Vector3d(tx, 0.1, 0)),
66  SimilarityTransform3(1, Eigen::Vector4d(1, qx + 0.05, 0, 0),
67  Eigen::Vector3d(tx, 0.2, 0)),
68  SimilarityTransform3(1, Eigen::Vector4d(1, qx + 0.1, 0, 0),
69  Eigen::Vector3d(tx, 0.3, 0)),
70  }};
71 
72  std::array<Eigen::Matrix3x4d, kNumTforms> rel_tforms;
73  for (size_t i = 0; i < kNumTforms; ++i) {
74  Eigen::Vector4d rel_qvec;
75  Eigen::Vector3d rel_tvec;
76  ComputeRelativePose(orig_tforms[kRefTform].Rotation(),
77  orig_tforms[kRefTform].Translation(),
78  orig_tforms[i].Rotation(),
79  orig_tforms[i].Translation(), &rel_qvec, &rel_tvec);
80  rel_tforms[i] = ComposeProjectionMatrix(rel_qvec, rel_tvec);
81  }
82 
83  // Project points to cameras.
84  std::vector<GR6PEstimator::X_t> points1;
85  std::vector<GR6PEstimator::Y_t> points2;
86  for (size_t i = 0; i < points3D.size(); ++i) {
87  const Eigen::Vector3d point3D_camera1 =
88  rel_tforms[i % kNumTforms] * points3D[i].homogeneous();
89  Eigen::Vector3d point3D_camera2 = points3D[i];
90  orig_tforms[(i + 1) % kNumTforms].TransformPoint(&point3D_camera2);
91 
92  if (point3D_camera1.z() < 0 || point3D_camera2.z() < 0) {
93  continue;
94  }
95 
96  points1.emplace_back();
97  points1.back().rel_tform = rel_tforms[i % kNumTforms];
98  points1.back().xy = point3D_camera1.hnormalized();
99 
100  points2.emplace_back();
101  points2.back().rel_tform = rel_tforms[(i + 1) % kNumTforms];
102  points2.back().xy = point3D_camera2.hnormalized();
103  }
104 
105  RANSACOptions options;
106  options.max_error = 1e-3;
108  const auto report = ransac.Estimate(points1, points2);
109 
110  BOOST_CHECK_EQUAL(report.success, true);
111 
112  const double matrix_diff =
113  (orig_tforms[kRefTform].Matrix().topLeftCorner<3, 4>() - report.model)
114  .norm();
115  BOOST_CHECK_LE(matrix_diff, 1e-2);
116 
117  std::vector<double> residuals;
118  GR6PEstimator::Residuals(points1, points2, report.model, &residuals);
119  for (size_t i = 0; i < residuals.size(); ++i) {
120  BOOST_CHECK_LE(residuals[i], options.max_error);
121  }
122  }
123  }
124 }
static void Residuals(const std::vector< X_t > &points1, const std::vector< Y_t > &points2, const M_t &proj_matrix, std::vector< double > *residuals)
Report Estimate(const std::vector< typename Estimator::X_t > &X, const std::vector< typename Estimator::Y_t > &Y)
Definition: loransac.h:72
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