tools.cpp
Go to the documentation of this file.
1 #include "tools.h"
2 
3 #include <SimoxUtility/math/periodic/periodic_diff.h>
4 #include <SimoxUtility/math/periodic/periodic_mean.h>
5 
6 Eigen::Vector3f
7 visionx::pointCloudMedian(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud,
8  const pcl::PointIndices& indices)
9 {
10  std::vector<float> xs, ys, zs;
11  xs.reserve(cloud.size());
12  ys.reserve(cloud.size());
13  zs.reserve(cloud.size());
14 
15  auto processPoint = [&](const auto& p)
16  {
17  xs.push_back(p.x);
18  ys.push_back(p.y);
19  zs.push_back(p.z);
20  };
21 
22  if (indices.indices.empty())
23  {
24  for (const auto& p : cloud)
25  {
26  processPoint(p);
27  }
28  }
29  else
30  {
31  for (int i : indices.indices)
32  {
33  processPoint(cloud.at(size_t(i)));
34  }
35  }
36 
37  std::sort(xs.begin(), xs.end());
38  std::sort(ys.begin(), ys.end());
39  std::sort(zs.begin(), zs.end());
40 
41  size_t index = cloud.size() / 2;
42  return Eigen::Vector3f(xs[index], ys[index], zs[index]);
43 }
44 
46 visionx::fitPlaneSVD(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud, Eigen::Vector3f center)
47 {
48  return fitPlaneSVD(cloud, pcl::PointIndices(), center);
49 }
50 
52 visionx::fitPlaneSVD(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud,
53  const pcl::PointIndices& indices,
54  Eigen::Vector3f center)
55 {
56  /* Find SVD of A:
57  * [ ]
58  * [ (c1-c) ... (cm-c) ] (3xm)
59  * [ ]
60  *
61  * Best normal is left singular vector of least singular value
62  * according to: https://math.stackexchange.com/a/99317
63  */
64 
65  // Build A
67 
68  MatT A;
69  if (indices.indices.empty())
70  {
71  // A = Eigen::MatrixXf(3, cloud.size());
72  A = MatT(3, cloud.size());
73  for (size_t i = 0; i < cloud.size(); ++i)
74  {
75  A.col(int(i)) = Eigen::Vector3f(cloud[i].data) - center;
76  }
77  }
78  else
79  {
80  int i = 0;
81  A = MatT(3, indices.indices.size());
82  for (int index : indices.indices)
83  {
84  A.col(i++) = Eigen::Vector3f(cloud.at(size_t(index)).data) - center;
85  }
86  }
87 
88  // Compute SVD
89  Eigen::JacobiSVD<MatT> svd(A, Eigen::ComputeFullU);
90 
91  // A is 3xm => U is 3x3, V is mxm
92  Eigen::Vector3f normal = svd.matrixU().col(2);
93 
94  return Eigen::Hyperplane3f(normal, center);
95 }
96 
97 pcl::PointIndicesPtr
98 visionx::getPlaneInliers(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud,
99  Eigen::Hyperplane3f plane,
100  float maxDistance)
101 {
102  pcl::PointIndicesPtr inliers(new pcl::PointIndices);
103  for (size_t i = 0; i < cloud.size(); ++i)
104  {
105  if (plane.absDistance(Eigen::Vector3f(cloud[i].data)) <= maxDistance)
106  {
107  inliers->indices.push_back(int(i));
108  }
109  }
110  return inliers;
111 }
112 
113 float
114 visionx::hsvDistance(const pcl::PointXYZHSV& lhs,
115  const pcl::PointXYZHSV& rhs,
116  const Eigen::Vector3f& hsvWeights)
117 {
118  return hsvDistance(
119  Eigen::Vector3f(lhs.h, lhs.s, lhs.v), Eigen::Vector3f(rhs.h, rhs.s, rhs.v), hsvWeights);
120 }
121 
122 float
123 visionx::hsvDistance(const Eigen::Vector3f& lhs,
124  const Eigen::Vector3f& rhs,
125  const Eigen::Vector3f& hsvWeights)
126 {
127  Eigen::Array3f dists(simox::math::periodic_diff(lhs.x(), rhs.x(), 0.f, 360.f) / 180.f,
128  lhs.y() - rhs.y(),
129  lhs.z() - rhs.z());
130  Eigen::Array3f weighted = hsvWeights.normalized().array() * dists.abs();
131  return weighted.sum();
132 }
133 
134 Eigen::Vector3f
135 visionx::hsvMean(const pcl::PointCloud<pcl::PointXYZHSV>& hsvCloud, const std::vector<int>& indices)
136 {
137  // Average color.
138  std::vector<float> hues;
139  hues.reserve(indices.size());
140  float s = 0, v = 0;
141  for (int i : indices)
142  {
143  const auto& p = hsvCloud.at(size_t(i));
144  hues.push_back(p.h);
145  s += p.s;
146  v += p.v;
147  }
148  float h = simox::math::periodic_mean(hues, 0.f, 360.f);
149  Eigen::Vector3f hsv(h, s / indices.size(), v / indices.size());
150  return hsv;
151 }
152 
154 visionx::alignPlaneNormal(const Eigen::Hyperplane3f plane, const Eigen::Vector3f normal)
155 {
156  return plane.normal().dot(normal) >= 0 ? plane
157  : Eigen::Hyperplane3f(-plane.normal(), -plane.offset());
158 }
visionx::fitPlaneSVD
Eigen::Hyperplane3f fitPlaneSVD(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, const pcl::PointIndices &indices, Eigen::Vector3f center=Eigen::Vector3f::Zero())
Definition: tools.cpp:52
index
uint8_t index
Definition: EtherCATFrame.h:59
visionx::hsvDistance
float hsvDistance(const pcl::PointXYZHSV &lhs, const pcl::PointXYZHSV &rhs, const Eigen::Vector3f &hsvWeights=Eigen::Vector3f::Ones())
Definition: tools.cpp:114
visionx::pointCloudMedian
Eigen::Vector3f pointCloudMedian(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, const pcl::PointIndices &indices={})
Definition: tools.cpp:7
visionx::hsvMean
Eigen::Vector3f hsvMean(const pcl::PointCloud< pcl::PointXYZHSV > &hsvCloud, const std::vector< int > &indices)
Definition: tools.cpp:135
pcl::graph::indices
pcl::PointIndices::Ptr indices(const PCG &g)
Retrieve the indices of the points of the point cloud stored in a point cloud graph that actually bel...
Definition: point_cloud_graph.h:717
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
Eigen::Hyperplane3f
Hyperplane< float, 3 > Hyperplane3f
Definition: Elements.h:34
visionx::getPlaneInliers
pcl::PointIndicesPtr getPlaneInliers(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, Eigen::Hyperplane3f plane, float maxDistance)
Definition: tools.cpp:98
A
class A(deque< T, A >)) ARMARX_OVERLOAD_STD_HASH_FOR_ITERABLE((class T
Enables hashing of std::list.
visionx::alignPlaneNormal
Eigen::Hyperplane3f alignPlaneNormal(Eigen::Hyperplane3f plane, Eigen::Vector3f normal)
Flip plane if its normal does not point towards normal.
Definition: tools.cpp:154
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::view_selection::skills::direction::state::center
state::Type center(state::Type previous)
Definition: LookDirection.cpp:233
Eigen::Matrix
Definition: EigenForwardDeclarations.h:27
tools.h
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33