cylindrical_shell.cpp
Go to the documentation of this file.
2 
3 void CylindricalShell::fitCylinder(const PointCloud::Ptr &cloud, const std::vector<int> &indices,
4  const Eigen::Vector3d &normal, const Eigen::Vector3d &curvature_axis)
5 {
6  // rotate points into axis aligned coordinate frame
7  int n = indices.size();
8  Eigen::Matrix3d R;
9  R.col(0) = normal;
10  R.col(1) = curvature_axis;
11  R.col(2) = normal.cross(curvature_axis);
12  Eigen::Matrix<double, 3, Eigen::Dynamic> pts(3, n);
13  for (int i = 0; i < n; i++)
14  pts.col(i) << cloud->points[indices[i]].x, cloud->points[indices[i]].y, cloud->points[indices[i]].z;
15  Eigen::MatrixXd Rpts = R.transpose() * pts;
16 
17  // fit circle
18  Eigen::RowVectorXd x = Rpts.row(0);
19  Eigen::RowVectorXd y = Rpts.row(1);
20  Eigen::RowVectorXd z = Rpts.row(2);
21  Eigen::RowVectorXd x2 = x.cwiseProduct(x);
22  Eigen::RowVectorXd z2 = z.cwiseProduct(z);
23  Eigen::RowVectorXd one = Eigen::MatrixXd::Ones(1, n);
24 
25  Eigen::MatrixXd l(3, n);
26  l << x, z, one;
27  Eigen::RowVectorXd gamma = x2 + z2;
28 
29  Eigen::Matrix3d Q = l * l.transpose();
30  Eigen::Vector3d c = ((gamma.replicate(3, 1)).cwiseProduct(l)).rowwise().sum();
31 
32  Eigen::Vector3d paramOut = -1 * Q.inverse() * c;
33 
34  // compute circle parameters
35  Eigen::Vector2d circleCenter = -0.5 * paramOut.segment(0, 2);
36  double circleRadius = sqrt(0.25 * (paramOut(0) * paramOut(0) + paramOut(1) * paramOut(1)) - paramOut(2));
37  double axisCoord = y.sum() / n;
38 
39  // get cylinder parameters from circle parameters
40  Eigen::Vector3d centroid_cyl_no_rot;
41  centroid_cyl_no_rot << circleCenter(0), axisCoord, circleCenter(1);
42  this->centroid = R * centroid_cyl_no_rot;
43  this->radius = circleRadius;
44  this->extent = y.maxCoeff() - y.minCoeff();
45  this->curvature_axis = curvature_axis;
46  this->normal = normal;
47 }
48 
49 bool CylindricalShell::hasClearance(const PointCloud::Ptr &cloud, const std::vector<int>& nn_indices,
50  double maxHandAperture, double handleGap)
51 {
52  int min_points_inner = 40; // min number of points required to be within the inner cylinder
53  int gap_threshold = 5; // threshold below which the gap is considered to be large enough
54 
55  std::vector<int> cropped_indices;
56  for (std::size_t i = 0; i < nn_indices.size(); i++)
57  {
58  Eigen::Vector3d cropped = cloud->points[nn_indices[i]].getVector3fMap().cast<double>();
59  double axialDist = this->curvature_axis.dot(cropped - centroid);
60  if (fabs(axialDist) < this->extent / 2)
61  cropped_indices.push_back(i);
62  }
63 
64  Eigen::Matrix<double, 3, Eigen::Dynamic> croppedPts(3, cropped_indices.size());
65  for (std::size_t i = 0; i < cropped_indices.size(); i++)
66  croppedPts.col(i) = cloud->points[nn_indices[cropped_indices[i]]].getVector3fMap().cast<double>();
67 
68  Eigen::MatrixXd normalDiff = (Eigen::MatrixXd::Identity(3, 3) - curvature_axis * curvature_axis.transpose())
69  * (croppedPts - centroid.replicate(1, croppedPts.cols()));
70  Eigen::VectorXd normalDist = normalDiff.cwiseProduct(normalDiff).colwise().sum().cwiseSqrt();
71 
72  /* increase cylinder radius until number of points in gap is smaller than <gap_threshold> and
73  * number of points within the inner cylinder is larger than <min_points_inner> */
74  for (double r = this->radius; r <= maxHandAperture; r += 0.001)
75  {
76  int numInGap = ((normalDist.array() > r) * (normalDist.array() < r + handleGap) == true).count();
77  int numInside = (normalDist.array() <= r).count();
78  //~ printf("numInGap: %i, numInside: %i, \n", numInGap, numInside);
79 
80  if (numInGap < gap_threshold && numInside > min_points_inner)
81  {
82  this->radius = r;
83  return true;
84  }
85  }
86 
87  return false;
88 }
Eigen::Vector3d centroid
TFSIMD_FORCE_INLINE const tfScalar & y() const
void fitCylinder(const PointCloud::Ptr &cloud, const std::vector< int > &indices, const Eigen::Vector3d &normal, const Eigen::Vector3d &curvature_axis)
Fit a cylinder to a set of points in the cloud, using their indices, and the normal and the curvature...
bool hasClearance(const PointCloud::Ptr &cloud, const std::vector< int > &nn_indices, double maxHandAperture, double handleGap)
Check whether the gap between the inner and outer cylinder of the shell is free of obstacles and wide...
Eigen::Vector3d normal
TFSIMD_FORCE_INLINE const tfScalar & x() const
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
TFSIMD_FORCE_INLINE const tfScalar & z() const
Eigen::Vector3d curvature_axis


handle_detector
Author(s):
autogenerated on Mon Jun 10 2019 13:29:00