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 
7 Eigen::Vector3f 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 
45 
47  const pcl::PointCloud<pcl::PointXYZRGBA>& cloud, Eigen::Vector3f center)
48 {
49  return fitPlaneSVD(cloud, pcl::PointIndices(), center);
50 }
51 
52 
54  const pcl::PointCloud<pcl::PointXYZRGBA>& cloud, const pcl::PointIndices& indices,
55  Eigen::Vector3f center)
56 {
57  /* Find SVD of A:
58  * [ ]
59  * [ (c1-c) ... (cm-c) ] (3xm)
60  * [ ]
61  *
62  * Best normal is left singular vector of least singular value
63  * according to: https://math.stackexchange.com/a/99317
64  */
65 
66  // Build A
67  Eigen::MatrixXf A;
68  if (indices.indices.empty())
69  {
70  A = Eigen::MatrixXf(3, cloud.size());
71  for (size_t i = 0; i < cloud.size(); ++i)
72  {
73  A.col(int(i)) = Eigen::Vector3f(cloud[i].data) - center;
74  }
75  }
76  else
77  {
78  int i = 0;
79  A = Eigen::MatrixXf(3, indices.indices.size());
80  for (int index : indices.indices)
81  {
82  A.col(i++) = Eigen::Vector3f(cloud.at(size_t(index)).data) - center;
83  }
84  }
85 
86  // Compute SVD
87  Eigen::JacobiSVD<Eigen::MatrixXf> svd(A, Eigen::ComputeFullU);
88 
89  // A is 3xm => U is 3x3, V is mxm
90  Eigen::Vector3f normal = svd.matrixU().col(2);
91 
92  return Eigen::Hyperplane3f(normal, center);
93 }
94 
95 
96 pcl::PointIndicesPtr visionx::getPlaneInliers(
97  const pcl::PointCloud<pcl::PointXYZRGBA>& cloud, Eigen::Hyperplane3f plane, float maxDistance)
98 {
99  pcl::PointIndicesPtr inliers(new pcl::PointIndices);
100  for (size_t i = 0; i < cloud.size(); ++i)
101  {
102  if (plane.absDistance(Eigen::Vector3f(cloud[i].data)) <= maxDistance)
103  {
104  inliers->indices.push_back(int(i));
105  }
106  }
107  return inliers;
108 }
109 
110 
111 float visionx::hsvDistance(const pcl::PointXYZHSV& lhs, const pcl::PointXYZHSV& rhs,
112  const Eigen::Vector3f& hsvWeights)
113 {
114  return hsvDistance(Eigen::Vector3f(lhs.h, lhs.s, lhs.v), Eigen::Vector3f(rhs.h, rhs.s, rhs.v), hsvWeights);
115 }
116 
117 
118 float visionx::hsvDistance(const Eigen::Vector3f& lhs, const Eigen::Vector3f& rhs,
119  const Eigen::Vector3f& hsvWeights)
120 {
121  Eigen::Array3f dists(simox::math::periodic_diff(lhs.x(), rhs.x(), 0.f, 360.f) / 180.f,
122  lhs.y() - rhs.y(),
123  lhs.z() - rhs.z());
124  Eigen::Array3f weighted = hsvWeights.normalized().array() * dists.abs();
125  return weighted.sum();
126 }
127 
128 
129 Eigen::Vector3f visionx::hsvMean(const pcl::PointCloud<pcl::PointXYZHSV>& hsvCloud, const std::vector<int>& indices)
130 {
131  // Average color.
132  std::vector<float> hues;
133  hues.reserve(indices.size());
134  float s = 0, v = 0;
135  for (int i : indices)
136  {
137  const auto& p = hsvCloud.at(size_t(i));
138  hues.push_back(p.h);
139  s += p.s;
140  v += p.v;
141  }
142  float h = simox::math::periodic_mean(hues, 0.f, 360.f);
143  Eigen::Vector3f hsv(h, s / indices.size(), v / indices.size());
144  return hsv;
145 }
146 
147 
148 Eigen::Hyperplane3f visionx::alignPlaneNormal(const Eigen::Hyperplane3f plane, const Eigen::Vector3f normal)
149 {
150  return plane.normal().dot(normal) >= 0
151  ? plane
152  : Eigen::Hyperplane3f(- plane.normal(), - plane.offset());
153 }
visionx::fitPlaneSVD
Eigen::Hyperplane3f fitPlaneSVD(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, const pcl::PointIndices &indices, Eigen::Vector3f center=Eigen::Vector3f::Zero())
Definition: tools.cpp:53
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:111
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:129
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:737
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
Eigen::Hyperplane3f
Hyperplane< float, 3 > Hyperplane3f
Definition: Elements.h:38
visionx::getPlaneInliers
pcl::PointIndicesPtr getPlaneInliers(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, Eigen::Hyperplane3f plane, float maxDistance)
Definition: tools.cpp:96
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:148
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
tools.h
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33