farm-ng-core
inverse_depth.h
Go to the documentation of this file.
1 // Copyright (c) 2011, Hauke Strasdat
2 // Copyright (c) 2012, Steven Lovegrove
3 // Copyright (c) 2021, farm-ng, inc.
4 //
5 // Use of this source code is governed by an MIT-style
6 // license that can be found in the LICENSE file or at
7 // https://opensource.org/licenses/MIT.
8 
9 #pragma once
10 
12 
13 namespace sophus {
14 
15 /// Inverse depth point representation
16 ///
17 /// (a, b) := (x/z, y/z) and psi := 1/z
18 ///
19 /// following https://ethaneade.com/thesis_revised.pdf, pp. 79
20 ///
21 /// Let us assume we have Euclidean 3d point (x,y,z) in a local reference frame
22 /// (e.g. camera origin). One can construct an inverse depth point (in the same
23 /// local reference frame) as follows:
24 ///
25 /// First we project the point (x,y,z) through the origin (0,0,0) onto the z=1
26 /// plane. We call the projection (a, b) := (x/z, y/z).
27 ///
28 /// In other words, (a, b) is the intersection of the line through (0, 0, 0)
29 /// to (x, y, z) and the 2d Euclidean plane z=1.
30 ///
31 /// Now, we can describe almost any 3d point in our local reference frame as a
32 /// point (a',b') in the Euclidean plane z=1 and the inverse depth psi := 1/z.
33 ///
34 /// For example, the Euclidean point (2, 0, 8) is represented as
35 /// (a, b) = (2/8, 0/8) = (1/4, 0) and inverse depth psi = 1/8.
36 ///
37 /// The only Euclidean 3d point we cannot describe is the origin (0,0,0) (since
38 /// there are infinitely many lines through the origin which intersect with the
39 /// plane z=1).
40 ///
41 /// The advantage of using an inverse depth representation over Euclidean
42 /// representation is that we can also represent points at infinity.
43 /// Let (a,b) a 2d Euclidean point on our reference plane z=1; nothing stops us
44 /// from choosing a psi=0, which corresponds to a "z = 1/0 = infinity".
45 ///
46 /// In summary, using this representation, we can represent
47 /// - points at infinity: psi == 1/z == 0
48 /// - points close to +infinity: psi == 1/z == +e
49 /// - points close to -infinity: psi == 1/z == -e
50 /// - points one unit in front: psi == 1/z == +1
51 /// - points one unit behind: psi == 1/z == -1
52 /// - points close to zero, in front: psi == 1/z == +999999
53 /// - points close to zero, behind: psi == 1/z == -999999
54 ///
55 template <class TT>
57  public:
59 
60  static auto fromEuclideanPoint3(Eigen::Matrix<TT, 3, 1> const& p)
62  using std::abs;
63  SOPHUS_ASSERT_GE(abs(p.z()), sophus::kEpsilon<TT>);
64  return InverseDepthPoint3(p.x() / p.z(), p.y() / p.z(), 1.0 / p.z());
65  }
66 
67  static auto fromAbAndPsi(Eigen::Matrix<TT, 3, 1> const& ab_and_psi)
70  p.ab_and_psi_ = ab_and_psi;
71  return p;
72  }
73 
75  Eigen::Matrix<TT, 2, 1> const& proj_in_z1_plane, TT const& one_by_z)
76  : ab_and_psi_(proj_in_z1_plane[0], proj_in_z1_plane[1], one_by_z) {
77  SOPHUS_ASSERT_GE(ab_and_psi_.norm(), sophus::kEpsilon<TT>);
78  }
79 
80  InverseDepthPoint3(TT const& x_by_z, TT const& y_by_z, TT const& one_by_z)
81  : ab_and_psi_(x_by_z, y_by_z, one_by_z) {}
82 
83  // Returns the projection of the point (x,y,z) onto the plane z=1.
84  // Hence (a, b) = ("x / z", "y / z").
85  [[nodiscard]] auto projInZ1Plane() const -> Eigen::Matrix<TT, 2, 1> {
86  return ab_and_psi_.template head<2>();
87  }
88 
89  /// Returns inverse depth psi, hence "1 / z".
90  [[nodiscard]] auto psi() const -> TT const& { return ab_and_psi_[2]; }
91  auto psi() -> TT& { return ab_and_psi_[2]; }
92 
93  [[nodiscard]] auto data() const -> TT const* { return ab_and_psi_.data(); }
94 
95  auto data() -> TT* { return ab_and_psi_.data(); }
96 
97  [[nodiscard]] auto params() const -> Eigen::Matrix<TT, 3, 1> const& {
98  return ab_and_psi_;
99  }
100 
101  /// Precondition: psi must not be close to 0, hence z must not be near
102  /// infinity.
103  [[nodiscard]] auto toEuclideanPoint3() const -> Eigen::Matrix<TT, 3, 1> {
104  using std::abs;
105  SOPHUS_ASSERT_GE(abs(psi()), sophus::kEpsilon<TT>);
106 
107  return Eigen::Matrix<TT, 3, 1>(
108  ab_and_psi_.x() / psi(), ab_and_psi_.y() / psi(), TT(1) / psi());
109  }
110 
111  private:
112  Eigen::Matrix<TT, 3, 1> ab_and_psi_;
113 };
114 
116 
117 } // namespace sophus
SOPHUS_ASSERT_GE
#define SOPHUS_ASSERT_GE(...)
Definition: common.h:42
Eigen
Definition: params.h:72
sophus::InverseDepthPoint3::InverseDepthPoint3
InverseDepthPoint3()
Definition: inverse_depth.h:58
sophus
Image MutImage, owning images types.
Definition: num_diff.h:20
sophus::InverseDepthPoint3::toEuclideanPoint3
auto toEuclideanPoint3() const -> Eigen::Matrix< TT, 3, 1 >
Precondition: psi must not be close to 0, hence z must not be near infinity.
Definition: inverse_depth.h:103
sophus::InverseDepthPoint3
Inverse depth point representation.
Definition: inverse_depth.h:56
sophus::InverseDepthPoint3::psi
auto psi() -> TT &
Definition: inverse_depth.h:91
sophus::InverseDepthPoint3::InverseDepthPoint3
InverseDepthPoint3(TT const &x_by_z, TT const &y_by_z, TT const &one_by_z)
Definition: inverse_depth.h:80
sophus::InverseDepthPoint3::fromAbAndPsi
static auto fromAbAndPsi(Eigen::Matrix< TT, 3, 1 > const &ab_and_psi) -> InverseDepthPoint3
Definition: inverse_depth.h:67
sophus::InverseDepthPoint3::data
auto data() const -> TT const *
Definition: inverse_depth.h:93
sophus::InverseDepthPoint3::fromEuclideanPoint3
static auto fromEuclideanPoint3(Eigen::Matrix< TT, 3, 1 > const &p) -> InverseDepthPoint3
Definition: inverse_depth.h:60
sophus::InverseDepthPoint3::projInZ1Plane
auto projInZ1Plane() const -> Eigen::Matrix< TT, 2, 1 >
Definition: inverse_depth.h:85
sophus::InverseDepthPoint3::data
auto data() -> TT *
Definition: inverse_depth.h:95
homogeneous.h
sophus::InverseDepthPoint3::InverseDepthPoint3
InverseDepthPoint3(Eigen::Matrix< TT, 2, 1 > const &proj_in_z1_plane, TT const &one_by_z)
Definition: inverse_depth.h:74
sophus::InverseDepthPoint3::params
auto params() const -> Eigen::Matrix< TT, 3, 1 > const &
Definition: inverse_depth.h:97
sophus::InverseDepthPoint3::psi
auto psi() const -> TT const &
Returns inverse depth psi, hence "1 / z".
Definition: inverse_depth.h:90