4 const Eigen::Vector3d &normal,
const Eigen::Vector3d &curvature_axis)
7 int n = indices.size();
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;
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);
25 Eigen::MatrixXd l(3, n);
27 Eigen::RowVectorXd gamma = x2 + z2;
29 Eigen::Matrix3d Q = l * l.transpose();
30 Eigen::Vector3d c = ((gamma.replicate(3, 1)).cwiseProduct(l)).rowwise().sum();
32 Eigen::Vector3d paramOut = -1 * Q.inverse() * c;
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;
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();
50 double maxHandAperture,
double handleGap)
52 int min_points_inner = 40;
53 int gap_threshold = 5;
55 std::vector<int> cropped_indices;
56 for (std::size_t i = 0; i < nn_indices.size(); i++)
58 Eigen::Vector3d cropped = cloud->points[nn_indices[i]].getVector3fMap().cast<
double>();
60 if (fabs(axialDist) < this->
extent / 2)
61 cropped_indices.push_back(i);
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>();
69 * (croppedPts -
centroid.replicate(1, croppedPts.cols()));
70 Eigen::VectorXd normalDist = normalDiff.cwiseProduct(normalDiff).colwise().sum().cwiseSqrt();
74 for (
double r = this->
radius; r <= maxHandAperture; r += 0.001)
76 int numInGap = ((normalDist.array() > r) * (normalDist.array() < r + handleGap) ==
true).count();
77 int numInside = (normalDist.array() <= r).count();
80 if (numInGap < gap_threshold && numInside > min_points_inner)
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...
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