OOBB.hpp
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #ifdef CGAL_FOUND
5 
6 #include <type_traits>
7 
8 #pragma GCC diagnostic push
9 #pragma GCC diagnostic ignored "-Wpedantic"
10 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
11 #include <CGAL/convex_hull_2.h>
12 #include <CGAL/min_quadrilateral_2.h>
13 #pragma GCC diagnostic pop
14 
15 #include <pcl/point_cloud.h>
16 #include <pcl/point_types.h>
17 
18 #include <SimoxUtility/shapes/OrientedBox.h>
19 #include <SimoxUtility/shapes/XYConstrainedOrientedBox.h>
20 
23 
24 #include "../VisitPointLikeContainer.h"
25 
26 namespace armarx
27 {
28  template<class ST>
29  Eigen::Matrix<ST, 3, 3> normalToRotation(const Eigen::Matrix<ST, 3, 1>& normal)
30  {
31  using VectorT = Eigen::Matrix<ST, 3, 1>;
32  using MatrixT = Eigen::Matrix<ST, 3, 3>;
33 
34  MatrixT mx;
35  mx.col(0) = normal.normalized();
36  const VectorT other = (mx.col(0) == VectorT::UnitZ()) ? VectorT::UnitX() : VectorT::UnitZ();
37  mx.col(1) = mx.col(0).cross(other).normalized();
38  mx.col(2) = mx.col(0).cross(mx.col(1)).normalized();
39 
40  return mx;
41  }
42 
43  template<class T>
44  simox::OrientedBox<double> calculate2dOOBB(const T& cloud, const Eigen::Vector3d& dir)
45  {
46  ARMARX_CHECK_GREATER(dir.norm(), 0.01) << VAROUT(dir.transpose());
47  const Eigen::Vector3d normal = dir.normalized();
48  using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
49  using Point_2 = Kernel::Point_2;
50  using Polygon_2 = CGAL::Polygon_2<Kernel>;
51 
52  const Eigen::Matrix3d boxFrame = normalToRotation(normal);
53  // const Eigen::Matrix3d boxFrame = Eigen::Matrix3d::Identity();
54 
55  std::vector<Point_2> allProjected;
56  double allMaxX = -std::numeric_limits<double>::infinity();
57  double allMinX = +std::numeric_limits<double>::infinity();
58  {
59  const auto& consume = [&](auto x, auto y, auto z)
60  {
61  const Eigen::Vector3d t = boxFrame.transpose() * Eigen::Vector3d{x, y, z};
62  allProjected.emplace_back(t.y(), t.z());
63  allMinX = std::min(allMinX, t.x());
64  allMaxX = std::max(allMaxX, t.x());
65 
66  };
67  const auto& resize = [&](auto size)
68  {
69  allProjected.reserve(size);
70  };
71  VisitPointLikeContainer(cloud, resize, consume);
72  }
73  ARMARX_CHECK(!allProjected.empty());
74 
75  std::vector<Point_2> chullAll;
76  CGAL::convex_hull_2(allProjected.begin(), allProjected.end(), std::back_inserter(chullAll));
77 
78  Polygon_2 polyAll;
79  CGAL::min_rectangle_2(chullAll.begin(), chullAll.end(), std::back_inserter(polyAll));
80  const auto& polyps = polyAll.container();
81 
82  ARMARX_CHECK_EQUAL(polyps.size(), 4)
83  << '\n' << VAROUT(normal.transpose())
84  << '\n' << VAROUT(boxFrame)
85  << '\n' << VAROUT(allProjected.size())
86  << '\n' << VAROUT(chullAll.size())
87  << '\n' << VAROUT(polyAll.container().size());
88 
89  const auto v0 = polyps.at(0) - polyps.at(1);
90  const auto v1 = polyps.at(2) - polyps.at(1);
92  {
93  Eigen::Vector3d{allMinX, polyps.at(1).x(), polyps.at(1).y()}, //corner
94  Eigen::Vector3d{allMaxX - allMinX, 0, 0}, //v3 (in local frame it is x)
95  Eigen::Vector3d{0, v0.x(), v0.y()}, //v1
96  Eigen::Vector3d{0, v1.x(), v1.y()} //v2
97  }.transformed(boxFrame);
98  }
99 
100  template<class T>
101  simox::XYConstrainedOrientedBox<double> calculateXYOOBB(const T& cloud)
102  {
103  const auto oobb = calculate2dOOBB(cloud, Eigen::Vector3d::UnitZ());
104  ARMARX_CHECK_GREATER(std::abs(oobb.axis_x().dot(Eigen::Vector3d::UnitZ())), 0.99)
105  << '\n' << VAROUT(oobb.transformation())
106  << '\n' << VAROUT(oobb.dimensions())
107  << '\n' << VAROUT(oobb.axis_x().transpose());
108 
109 
110  const Eigen::Vector3d e1 = oobb.extend(1);
111  const Eigen::Vector3d e2 = oobb.extend(2);
112 
113  return
114  {
115  oobb.translation(),
116  {e1(0), e1(1)},
117  {e2(0), e2(1)},
118  oobb.dimension(0)
119  };
120  }
121 
122 
123  template<class T>
124  simox::OrientedBox<double> calculateDouble2dOOBB(const T& cloud)
125  {
126  const auto box1 = calculate2dOOBB(cloud, Eigen::Vector3d::UnitZ());
127 
128  ARMARX_CHECK_GREATER(std::abs(box1.axis_x().normalized().dot(Eigen::Vector3d::UnitZ())), 0.99)
129  << '\n' << VAROUT(box1.transformation());
130 
131  const Eigen::Vector3d norm =
132  (box1.axis_y().norm() < box1.axis_z().norm()) ?
133  box1.axis_y() : box1.axis_z();
134 
135  const auto box2 = calculate2dOOBB(cloud, norm);
136  ARMARX_CHECK_GREATER(std::abs(box2.axis_x().normalized().dot(norm.normalized())), 0.99)
137  << '\n' << VAROUT(box2.transformation())
138  << '\n' << VAROUT(norm.transpose());
139 
140  return box2;
141  }
142 
143 
144  template<class T>
145  inline std::vector<Eigen::Vector3f> trimXYZHistogram(
146  const T& cloud,
147  const Eigen::Matrix3f& transform,
148  const float trimEachSideBy)
149  {
150  std::vector<float> valuesX;
151  std::vector<float> valuesY;
152  std::vector<float> valuesZ;
153  std::size_t sz = 0;
154  {
155  const auto& consume = [&](auto x, auto y, auto z)
156  {
157  const Eigen::Vector3f ted = transform * Eigen::Vector3f{x, y, z};
158  valuesX.emplace_back(ted.x());
159  valuesY.emplace_back(ted.y());
160  valuesZ.emplace_back(ted.z());
161  };
162  const auto& resize = [&](auto size)
163  {
164  sz = size;
165  valuesX.reserve(size);
166  valuesY.reserve(size);
167  valuesZ.reserve(size);
168  };
169  VisitPointLikeContainer(cloud, resize, consume);
170  }
171 
172  std::sort(valuesX.begin(), valuesX.end());
173  std::sort(valuesY.begin(), valuesY.end());
174  std::sort(valuesZ.begin(), valuesZ.end());
175 
176  const std::size_t idxLo = sz * trimEachSideBy;
177  const std::size_t idxHi = sz - std::max(idxLo, 1ul);
178  const float loX = valuesX.at(idxLo);
179  const float hiX = valuesX.at(idxHi);
180  const float loY = valuesY.at(idxLo);
181  const float hiY = valuesY.at(idxHi);
182  const float loZ = valuesZ.at(idxLo);
183  const float hiZ = valuesZ.at(idxHi);
184 
185 
186  std::vector<Eigen::Vector3f> result;
187  {
188  const auto& consume = [&](auto x, auto y, auto z)
189  {
190  const Eigen::Vector3f ted = transform * Eigen::Vector3f{x, y, z};
191  if (
192  ted.x() <= hiX && ted.x() >= loX &&
193  ted.y() <= hiY && ted.y() >= loY &&
194  ted.z() <= hiZ && ted.z() >= loZ
195  )
196  {
197  result.emplace_back(x, y, z);
198  }
199  };
200  const auto& resize = [&](auto) {};
201  VisitPointLikeContainer(cloud, resize, consume);
202  }
203 
204  return result;
205  }
206 
207 }
208 
209 #endif
armarx::VisitPointLikeContainer
void VisitPointLikeContainer(const auto &cloud, auto &&perElem, auto &&sizeInfo)
Definition: VisitPointLikeContainer.h:273
ARMARX_CHECK_GREATER
#define ARMARX_CHECK_GREATER(lhs, rhs)
This macro evaluates whether lhs is greater (>) than rhs and if it turns out to be false it will thro...
Definition: ExpressionException.h:116
trace.h
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:253
max
T max(T t1, T t2)
Definition: gdiam.h:48
ExpressionException.h
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:600
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:315
simox::OrientedBox
Definition: ice_conversions.h:18
Eigen::Matrix
Definition: EigenForwardDeclarations.h:27
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
min
T min(T t1, T t2)
Definition: gdiam.h:42
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
norm
double norm(const Point &a)
Definition: point.hpp:94