farm-ng-core
ray.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 
11 #include "sophus/common/common.h"
12 #include "sophus/lie/isometry2.h"
13 #include "sophus/lie/isometry3.h"
14 #include "sophus/lie/similarity2.h"
15 #include "sophus/lie/similarity3.h"
17 
18 #include <Eigen/Dense>
19 
20 #include <optional>
21 
22 namespace sophus {
23 
24 // Forward declarations
25 template <class TScalar, int kN>
26 class Ray;
27 
28 // Convenience typedefs
29 template <class TScalar>
31 template <class TScalar>
33 
36 
37 template <class TScalar, int kN>
38 class Ray {
39  public:
40  Ray(Eigen::Matrix<TScalar, kN, 1> const& origin,
42  : origin_(origin), direction_(direction) {}
43 
44  Ray(Ray const&) = default;
45  auto operator=(Ray const&) -> Ray& = default;
46 
47  [[nodiscard]] auto origin() const -> Eigen::Matrix<TScalar, kN, 1> const& {
48  return origin_;
49  }
50  [[nodiscard]] auto origin() -> Eigen::Matrix<TScalar, kN, 1>& {
51  return origin_;
52  }
53 
54  [[nodiscard]] auto direction() const -> UnitVector<TScalar, kN> const& {
55  return direction_;
56  }
57  [[nodiscard]] auto direction() -> UnitVector<TScalar, kN>& {
58  return direction_;
59  }
60 
61  [[nodiscard]] auto pointAt(TScalar lambda) const
62  -> Eigen::Matrix<TScalar, kN, 1> {
63  return this->origin_ + lambda * this->direction_.params();
64  }
65 
67  double lambda;
68  Eigen::Matrix<TScalar, kN, 1> point;
69  };
70 
71  [[nodiscard]] auto intersect(Eigen::Hyperplane<TScalar, kN> const& plane)
72  const -> std::optional<IntersectionResult> {
73  using std::abs;
74  TScalar dot_prod = plane.normal().dot(this->direction_.vector());
75  if (abs(dot_prod) < sophus::kEpsilon<TScalar>) {
76  return std::nullopt;
77  }
78  IntersectionResult result;
79  result.lambda =
80  -(plane.offset() + plane.normal().dot(this->origin_)) / dot_prod;
81  result.point = this->pointAt(result.lambda);
82  return result;
83  }
84 
85  [[nodiscard]] auto projection(Eigen::Matrix<TScalar, kN, 1> const& point)
86  const -> Eigen::Matrix<TScalar, kN, 1> {
87  return origin_ +
88  direction_.getVector().dot(point - origin_) * direction_.vector();
89  }
90 
91  private:
92  Eigen::Matrix<TScalar, kN, 1> origin_;
93  UnitVector<TScalar, kN> direction_;
94 };
95 
96 template <class TT>
97 inline auto operator*(
98  Isometry2<TT> const& bar_from_foo, Ray<TT, 2> const& ray_foo)
99  -> Ray<TT, 2> {
100  return Ray<TT, 2>(
101  bar_from_foo * ray_foo.origin(),
102  bar_from_foo.so2() * ray_foo.direction());
103 }
104 
105 template <class TT>
106 inline auto operator*(
107  Isometry3<TT> const& bar_from_foo, Ray<TT, 3> const& ray_foo)
108  -> Ray<TT, 3> {
109  return Ray<TT, 3>(
110  bar_from_foo * ray_foo.origin(),
111  bar_from_foo.so3() * ray_foo.direction());
112 }
113 
114 // Arbitrary 6-DoF transformation of a unit vector promotes it to a ray
115 // having a potentially non-zero origin.
116 template <class TT>
117 inline auto operator*(
118  Isometry3<TT> const& bar_from_foo, UnitVector<TT, 3> const& v_foo)
119  -> Ray<TT, 3> {
120  return Ray<TT, 3>(bar_from_foo.translation(), bar_from_foo.so3() * v_foo);
121 }
122 
123 template <class TT>
124 auto operator*(Similarity2<TT> const& b_from_a, Ray2<TT> const& ray_a)
125  -> Ray2<TT> {
126  return Ray2<TT>(b_from_a * ray_a.origin(), b_from_a * ray_a.direction());
127 }
128 
129 template <class TT>
130 auto operator*(Similarity3<TT> const& b_from_a, Ray3<TT> const& ray_a)
131  -> Ray3<TT> {
132  return Ray3<TT>(b_from_a * ray_a.origin(), b_from_a * ray_a.direction());
133 }
134 
135 template <class TT>
140 };
141 
142 /// For two parametric lines in lambda0 and lambda1 respectively,
143 /// ```
144 /// line_0: x(lambda0) = o0 + lambda0 * d0
145 /// line_1: y(lambda1) = o1 + lambda1 * d1
146 /// ```
147 /// returns distances [lambda0, lambda1] along the respective rays,
148 /// corresponding to the closest approach of x and y according to an l2 distance
149 /// measure. lambda0 and lambda1 may be positive or negative. If line_0 and
150 /// line_1 are parallel, returns nullopt as no unique solution exists
151 template <class TT>
152 auto closestApproachParameters(Ray3<TT> const& line_0, Ray3<TT> const& line_1)
153  -> std::optional<ClosestApproachResult<TT>> {
154  using std::abs;
155  // Closest approach when line segment connecting closest points on each line
156  // is perpendicular to both d0 and d1, thus:
157  // ```
158  // x(lambda0)-y(lambda1) = theta*(d0 X d1), for free scalar theta.
159  // => o0-o1 + lambda0*d0 - lambda1*d1 - theta*(d0Xd1) = 0
160  // => (d0|-d1|-d0Xd1).(lambda0,lambda1,theta)^T = -(o0-o1)
161  // A . x = b
162  // ```
163 
164  Eigen::Vector<TT, 3> const d0_cross_d1 =
165  line_0.direction().params().cross(line_1.direction().params());
166 
167  TT const d0_cross_s1_length = d0_cross_d1.norm();
168 
169  if (d0_cross_s1_length < kEpsilon<TT>) {
170  // Rays are parallel so no unique solution exists.
171  return std::nullopt;
172  }
173 
174  Eigen::Matrix<TT, 3, 3> mat_a;
175  mat_a << line_0.direction().params(), -line_1.direction().params(),
176  -d0_cross_d1;
177 
178  Eigen::Vector<TT, 3> const b = line_1.origin() - line_0.origin();
179 
180  Eigen::Vector<TT, 3> const x = mat_a.lu().solve(b);
181  TT const lambda0 = x[0];
182  TT const lambda1 = x[1];
183  TT const min_distance = d0_cross_s1_length * x[2];
184 
185  return ClosestApproachResult<TT>{lambda0, lambda1, min_distance};
186 }
187 
188 /// For two lines ``line_0`` and ``line_1`` returns the mid-point of the line
189 /// segment connecting one point from each of the lines which are closest to
190 /// one another according to the l2 distance measure.
191 ///
192 /// If line_0 and line_1 are parallel, returns nullopt as no unique solution
193 /// exists
194 template <class TT>
195 auto closestApproach(Ray3<TT> const& line_0, Ray3<TT> const& line_1)
196  -> std::optional<Eigen::Vector3<TT>> {
197  auto maybe_result = closestApproachParameters(line_0, line_1);
198  if (!maybe_result) {
199  return std::nullopt;
200  }
201  return (line_0.pointAt(maybe_result->lambda0) +
202  line_1.pointAt(maybe_result->lambda1)) /
203  static_cast<TT>(2.0);
204 }
205 
206 } // namespace sophus
sophus::Ray::direction
auto direction() -> UnitVector< TScalar, kN > &
Definition: ray.h:57
sophus::Ray::pointAt
auto pointAt(TScalar lambda) const -> Eigen::Matrix< TScalar, kN, 1 >
Definition: ray.h:61
sophus::Ray::direction
auto direction() const -> UnitVector< TScalar, kN > const &
Definition: ray.h:54
similarity3.h
sophus::Similarity2
Definition: similarity2.h:22
Eigen
Definition: params.h:72
sophus::Ray::IntersectionResult::point
Eigen::Matrix< TScalar, kN, 1 > point
Definition: ray.h:68
sophus::UnitVector
Definition: lie_group.h:14
sophus
Image MutImage, owning images types.
Definition: num_diff.h:20
sophus::Ray::projection
auto projection(Eigen::Matrix< TScalar, kN, 1 > const &point) const -> Eigen::Matrix< TScalar, kN, 1 >
Definition: ray.h:85
similarity2.h
sophus::closestApproach
auto closestApproach(Ray3< TT > const &line_0, Ray3< TT > const &line_1) -> std::optional< Eigen::Vector3< TT >>
For two lines line_0 and line_1 returns the mid-point of the line segment connecting one point from e...
Definition: ray.h:195
sophus::Ray::Ray
Ray(Eigen::Matrix< TScalar, kN, 1 > const &origin, UnitVector< TScalar, kN > const &direction)
Definition: ray.h:40
isometry3.h
sophus::operator*
auto operator*(Isometry2< TT > const &bar_from_foo, Ray< TT, 2 > const &ray_foo) -> Ray< TT, 2 >
Definition: ray.h:97
isometry2.h
sophus::Ray::IntersectionResult::lambda
double lambda
Definition: ray.h:67
sophus::Ray::intersect
auto intersect(Eigen::Hyperplane< TScalar, kN > const &plane) const -> std::optional< IntersectionResult >
Definition: ray.h:71
sophus::ClosestApproachResult
Definition: ray.h:136
sophus::Isometry2
Definition: isometry2.h:22
sophus::Ray::origin
auto origin() -> Eigen::Matrix< TScalar, kN, 1 > &
Definition: ray.h:50
unit_vector.h
sophus::Ray::origin
auto origin() const -> Eigen::Matrix< TScalar, kN, 1 > const &
Definition: ray.h:47
sophus::ClosestApproachResult::lambda0
TT lambda0
Definition: ray.h:137
common.h
sophus::closestApproachParameters
auto closestApproachParameters(Ray3< TT > const &line_0, Ray3< TT > const &line_1) -> std::optional< ClosestApproachResult< TT >>
For two parametric lines in lambda0 and lambda1 respectively,.
Definition: ray.h:152
sophus::Ray
Definition: ray.h:26
sophus::Isometry3< TT >
sophus::ClosestApproachResult::min_distance
TT min_distance
Definition: ray.h:139
sophus::Similarity3
Definition: similarity3.h:22
sophus::Ray::IntersectionResult
Definition: ray.h:66
sophus::ClosestApproachResult::lambda1
TT lambda1
Definition: ray.h:138
sophus::Ray::operator=
auto operator=(Ray const &) -> Ray &=default