farm-ng-core
point_transform.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 #include "sophus/lie/se3.h"
14 
15 namespace sophus {
16 
17 /// Projects 3-point (a,b,psi) = (x/z,y/z,1/z) through the origin (0,0,0) onto
18 /// the plane z=1. Hence it returns (a,b) = (x/z, y/z).
19 template <class TT>
20 auto proj(InverseDepthPoint3<TT> const& inverse_depth_point)
21  -> Eigen::Matrix<TT, 2, 1> {
22  return inverse_depth_point.projInZ1Plane();
23 }
24 
25 /// Returns point derivative of inverse depth point projection:
26 ///
27 /// Dx proj(x) with x = (a,b,psi) being an inverse depth point.
28 template <class TT>
29 auto dxProjX(InverseDepthPoint3<TT> const& /*inverse_depth_point*/)
30  -> Eigen::Matrix<TT, 2, 3> {
31  Eigen::Matrix<TT, 2, 3> dx;
32  dx.setIdentity();
33  return dx;
34 }
35 
36 /// Returns pose derivative of inverse depth point projection at the identity:
37 ///
38 /// Dx proj(exp(x) * y) at x=0
39 ///
40 /// with y = (a,b,psi) being an inverse depth point.
41 template <class TT>
42 auto dxProjExpXPointAt0(InverseDepthPoint3<TT> const& inverse_depth_point)
43  -> Eigen::Matrix<TT, 2, 6> {
44  Eigen::Matrix<TT, 2, 6> dx;
45  TT i = TT(1);
46  TT psi = inverse_depth_point.psi();
47 
48  TT a = inverse_depth_point.projInZ1Plane().x();
49  TT b = inverse_depth_point.projInZ1Plane().y();
50  // clang-format off
51  dx <<
52  psi, 0, -psi * a, -a*b, a*a + i, -b,
53  0, psi, -psi * b, -b*b - i, a*b, a;
54  // clang-format on
55  return dx;
56 }
57 
58 /// Transforms inverse_depth point in frame bar to a scaled inverse depth point
59 /// in frame foo. Here the scale is psi, the input inverse depth.
60 ///
61 /// Given (a,b,psi) being the inverse depth point in frame bar, it returns
62 ///
63 /// psi * (foo_from_bar * inverse_depth_point_in_bar.toEuclideanPoint3())
64 ///
65 /// for psi!=0.
66 template <class TT>
68  sophus::Isometry3<TT> const& foo_from_bar,
69  InverseDepthPoint3<TT> const& inverse_depth_point_in_bar)
70  -> Eigen::Matrix<TT, 3, 1> {
71  return foo_from_bar.so3() *
72  unproj(inverse_depth_point_in_bar.projInZ1Plane()) +
73  inverse_depth_point_in_bar.psi() * foo_from_bar.translation();
74 }
75 
76 /// Transforms inverse_depth point from frame bar to frame foo followed by a
77 /// projection.
78 ///
79 /// If psi != 0, hence the point is not at +/- infinity, this function is
80 /// equivalent to:
81 ///
82 /// camProj(foo_from_bar * inverse_depth_point_in_bar.toEuclideanPoint3());
83 ///
84 /// However, this function can also applied when 1/z==0, hence the point is at
85 /// +/- infinity.
86 template <class TT>
88  sophus::Isometry3<TT> const& foo_from_bar,
89  InverseDepthPoint3<TT> const& inverse_depth_point_in_bar)
90  -> Eigen::Matrix<TT, 2, 1> {
91  // R * (x,y,z) + t
92  // = z * [R * (x/z, y/z, 1) + 1/z * t]
93  //
94  // Hence:
95  // proj(R * (x,y,z) + t)
96  // = proj(1/z * [R * (x,y,z) + t]) { since proj(xyz) == proj(l * xyz) }
97  // = proj(R * (x/z, y/z, 1) + 1/z * t)
98  //
99  // qed.
100  // with R := foo_from_bar.so3(),
101  // t := foo_from_bar.translation()
102  // (x/z, y/z, 1) := unproj(rojInZ1Plane())
103  // 1/z := psi()
104  //
105  return proj(scaledTransform(foo_from_bar, inverse_depth_point_in_bar));
106 }
107 
108 /// Functor to efficiently transform a number of point given a Isometry3 pose.
109 ///
110 /// When transforming a point `point_in_bar` given a sophus::Isometry3 pose
111 /// `foo_from_bar`, one can simply use
112 ///
113 /// ``Eigen::Vector3d = foo_from_bar * point_in_bar;``
114 ///
115 /// Internally, this applies the (unit) quaternion to the left and the right of
116 /// the point to rotate it and then adds the translation:
117 ///
118 /// point_in_foo = q*point_in_bar*q' + bar_origin_in_foo.
119 ///
120 /// If there are a lot of point to transform, there is a more efficient
121 /// way using the rotation matrix R which can be precomputed from the quaternion
122 /// q.
123 ///
124 /// point_in_foo = R * point_in_bar + bar_origin_in_foo
125 ///
126 /// This is what this functor is for.
127 template <class TT>
129  public:
130  PointTransformer() = default;
131  explicit PointTransformer(sophus::Isometry3<TT> const& foo_from_bar)
132  : foo_from_bar_(foo_from_bar),
133  foo_rotation_bar_(foo_from_bar.so3().matrix()),
134  bar_origin_in_foo_(foo_from_bar.translation()) {}
135 
136  /// Transforms a 3-point from frame bar to frame foo.
137  [[nodiscard]] auto transform(Eigen::Matrix<TT, 3, 1> const& point_in_bar)
138  const -> Eigen::Matrix<TT, 3, 1> {
139  return foo_rotation_bar_ * point_in_bar + bar_origin_in_foo_;
140  }
141 
142  [[nodiscard]] auto scaledTransform(
143  InverseDepthPoint3<TT> const& inverse_depth_point_in_bar) const
144  -> Eigen::Matrix<TT, 3, 1> {
145  return foo_rotation_bar_ *
146  unproj(inverse_depth_point_in_bar.projInZ1Plane()) +
147  inverse_depth_point_in_bar.psi() * bar_origin_in_foo_;
148  }
149 
150  /// Transforms 3-point in frame bar to foo and projects it onto the
151  /// Euclidean plane z=1 in foo.
152  [[nodiscard]] auto projTransform(Eigen::Matrix<TT, 3, 1> const& point_in_bar)
153  const -> Eigen::Matrix<TT, 2, 1> {
154  return proj(foo_rotation_bar_ * point_in_bar + bar_origin_in_foo_);
155  }
156 
157  /// Transforms and projects the 3d inverse depth point in frame bar to the
158  /// Euclidean plane z=1 in foo.
159  [[nodiscard]] auto projTransform(
160  InverseDepthPoint3<TT> const& inverse_depth_point_in_bar) const
161  -> Eigen::Matrix<TT, 2, 1> {
162  return proj(scaledTransform(inverse_depth_point_in_bar));
163  }
164 
165  /// Returns pose derivative of inverse depth point projection at the identity:
166  ///
167  /// Dx proj(exp(x) * foo_from_bar * foo_in_bar.toEuclideanPoint3()) at x=0
168  ///
169  /// with foo_in_bar = (a,b,psi) being an inverse depth point.
170  [[nodiscard]] auto dxProjExpXTransformPointAt0(
171  InverseDepthPoint3<TT> const& inverse_depth_point_in_bar) const
172  -> Eigen::Matrix<TT, 2, 6> {
173  Eigen::Matrix<TT, 2, 6> dx;
174  TT i = TT(1);
175  TT psi = inverse_depth_point_in_bar.psi();
176  Eigen::Matrix<TT, 3, 1> scaled_point_in_foo =
177  scaledTransform(inverse_depth_point_in_bar);
178  TT x = scaled_point_in_foo[0];
179  TT y = scaled_point_in_foo[1];
180  TT z = scaled_point_in_foo[2];
181  TT z_sq = z * z;
182 
183  // clang-format off
184  dx <<
185  psi/z, 0, -psi * x / z_sq, -x*y/z_sq, x*x/z_sq + i, -y/z,
186  0, psi/z, -psi * y / z_sq, -y*y/z_sq - i, x*y/z_sq, x/z;
187  // clang-format on
188  return dx;
189  }
190 
191  // Assuming ProjectionZ1 based camera
192  [[nodiscard]] auto dxProjTransformX(
193  InverseDepthPoint3<TT> const& inverse_depth_point_in_bar) const
194  -> Eigen::Matrix<TT, 2, 3> {
195  Eigen::Vector3<TT> const& r0 = this->fooRotationBar().col(0);
196  Eigen::Vector3<TT> const& r1 = this->fooRotationBar().col(1);
197  Eigen::Vector3<TT> const& t = this->barOriginInFoo();
198 
199  Eigen::Matrix3<TT> mat_j;
200  mat_j << r0, r1, t;
201 
202  return ProjectionZ1::dxProjX(scaledTransform(inverse_depth_point_in_bar)) *
203  mat_j;
204  }
205 
206  [[nodiscard]] auto fooFromBar() const -> sophus::Isometry3<TT> const& {
207  return foo_from_bar_;
208  }
209  [[nodiscard]] auto fooRotationBar() const -> Eigen::Matrix<TT, 3, 3> const& {
210  return foo_rotation_bar_;
211  }
212  [[nodiscard]] auto barOriginInFoo() const -> Eigen::Matrix<TT, 3, 1> const& {
213  return bar_origin_in_foo_;
214  }
215 
216  private:
217  sophus::Isometry3<TT> foo_from_bar_;
218  Eigen::Matrix<TT, 3, 3> foo_rotation_bar_;
219  Eigen::Matrix<TT, 3, 1> bar_origin_in_foo_;
220 };
221 } // namespace sophus
sophus::unproj
auto unproj(Eigen::MatrixBase< TPoint > const &p, const typename TPoint::Scalar &z=1.0) -> Eigen::Vector< typename TPoint::Scalar, TPoint::RowsAtCompileTime+1 >
Maps point on the z=1 plane (a,b) to homogeneous representation of the same point: (z*a,...
Definition: homogeneous.h:31
Eigen
Definition: params.h:72
sophus::PointTransformer
Functor to efficiently transform a number of point given a Isometry3 pose.
Definition: point_transform.h:128
sophus::PointTransformer::PointTransformer
PointTransformer()=default
sophus::PointTransformer::fooFromBar
auto fooFromBar() const -> sophus::Isometry3< TT > const &
Definition: point_transform.h:206
sophus::PointTransformer::projTransform
auto projTransform(InverseDepthPoint3< TT > const &inverse_depth_point_in_bar) const -> Eigen::Matrix< TT, 2, 1 >
Transforms and projects the 3d inverse depth point in frame bar to the Euclidean plane z=1 in foo.
Definition: point_transform.h:159
sophus::PointTransformer::barOriginInFoo
auto barOriginInFoo() const -> Eigen::Matrix< TT, 3, 1 > const &
Definition: point_transform.h:212
sophus::ProjectionZ1::dxProjX
static auto dxProjX(Eigen::Matrix< TScalar, 3, 1 > const &p) -> Eigen::Matrix< TScalar, 2, 3 >
Returns point derivative of inverse depth point projection:
Definition: projection_z1.h:52
sophus
Image MutImage, owning images types.
Definition: num_diff.h:20
sophus::InverseDepthPoint3
Inverse depth point representation.
Definition: inverse_depth.h:56
sophus::PointTransformer::transform
auto transform(Eigen::Matrix< TT, 3, 1 > const &point_in_bar) const -> Eigen::Matrix< TT, 3, 1 >
Transforms a 3-point from frame bar to frame foo.
Definition: point_transform.h:137
sophus::PointTransformer::dxProjTransformX
auto dxProjTransformX(InverseDepthPoint3< TT > const &inverse_depth_point_in_bar) const -> Eigen::Matrix< TT, 2, 3 >
Definition: point_transform.h:192
sophus::PointTransformer::dxProjExpXTransformPointAt0
auto dxProjExpXTransformPointAt0(InverseDepthPoint3< TT > const &inverse_depth_point_in_bar) const -> Eigen::Matrix< TT, 2, 6 >
Returns pose derivative of inverse depth point projection at the identity:
Definition: point_transform.h:170
sophus::dxProjX
auto dxProjX(InverseDepthPoint3< TT > const &) -> Eigen::Matrix< TT, 2, 3 >
Returns point derivative of inverse depth point projection:
Definition: point_transform.h:29
sophus::PointTransformer::PointTransformer
PointTransformer(sophus::Isometry3< TT > const &foo_from_bar)
Definition: point_transform.h:131
inverse_depth.h
sophus::PointTransformer::fooRotationBar
auto fooRotationBar() const -> Eigen::Matrix< TT, 3, 3 > const &
Definition: point_transform.h:209
se3.h
sophus::PointTransformer::projTransform
auto projTransform(Eigen::Matrix< TT, 3, 1 > const &point_in_bar) const -> Eigen::Matrix< TT, 2, 1 >
Transforms 3-point in frame bar to foo and projects it onto the Euclidean plane z=1 in foo.
Definition: point_transform.h:152
projection_z1.h
sophus::projTransform
auto projTransform(sophus::Isometry3< TT > const &foo_from_bar, InverseDepthPoint3< TT > const &inverse_depth_point_in_bar) -> Eigen::Matrix< TT, 2, 1 >
Transforms inverse_depth point from frame bar to frame foo followed by a projection.
Definition: point_transform.h:87
sophus::Isometry3< TT >
sophus::scaledTransform
auto scaledTransform(sophus::Isometry3< TT > const &foo_from_bar, InverseDepthPoint3< TT > const &inverse_depth_point_in_bar) -> Eigen::Matrix< TT, 3, 1 >
Transforms inverse_depth point in frame bar to a scaled inverse depth point in frame foo....
Definition: point_transform.h:67
sophus::proj
auto proj(InverseDepthPoint3< TT > const &inverse_depth_point) -> Eigen::Matrix< TT, 2, 1 >
Projects 3-point (a,b,psi) = (x/z,y/z,1/z) through the origin (0,0,0) onto the plane z=1....
Definition: point_transform.h:20
sophus::dxProjExpXPointAt0
auto dxProjExpXPointAt0(InverseDepthPoint3< TT > const &inverse_depth_point) -> Eigen::Matrix< TT, 2, 6 >
Returns pose derivative of inverse depth point projection at the identity:
Definition: point_transform.h:42
sophus::PointTransformer::scaledTransform
auto scaledTransform(InverseDepthPoint3< TT > const &inverse_depth_point_in_bar) const -> Eigen::Matrix< TT, 3, 1 >
Definition: point_transform.h:142