| 73 | } |
| 74 | |
| 75 | void Cylinder::computeModel(const std::vector<TreeVertex> &landmarkVtxs, |
| 76 | const Scalar defaultTreeRadius, const Scalar featuresPerTree) |
| 77 | { |
| 78 | TreeVertex firstVtx = landmarkVtxs[2]; |
| 79 | std::vector<float> validRadii; |
| 80 | CloudT::Ptr tree(new CloudT); |
| 81 | |
| 82 | for (size_t i = 0; i < landmarkVtxs.size(); ++i) |
| 83 | { |
| 84 | TreeVertex vtx = landmarkVtxs[i]; |
| 85 | tree->push_back(vtx.coords); |
| 86 | |
| 87 | for (auto &vtxP : vtx.points) |
| 88 | { |
| 89 | vtxP.intensity = (float)firstVtx.treeId; |
| 90 | features.push_back(vtxP); |
| 91 | } |
| 92 | |
| 93 | model.radii.push_back(vtx.radius); |
| 94 | if (vtx.points.size() > 3) |
| 95 | { |
| 96 | validRadii.push_back(vtx.radius); |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | id = firstVtx.treeId; |
| 101 | auto bottomPt = landmarkVtxs[1].coords; |
| 102 | auto topPt = landmarkVtxs[landmarkVtxs.size() - 2].coords; |
| 103 | |
| 104 | model.root(0) = bottomPt.x; |
| 105 | model.root(1) = bottomPt.y; |
| 106 | model.root(2) = bottomPt.z; |
| 107 | |
| 108 | // if tree is too short, we don't use it |
| 109 | if (pcl::geometry::squaredDistance(bottomPt, topPt) < 1.5 || tree->size() == 0) |
| 110 | { |
| 111 | model.radius = -1; |
| 112 | return; |
| 113 | } |
| 114 | |
| 115 | //Create a model parameter object to record the result |
| 116 | pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); |
| 117 | pcl::PointIndices::Ptr inliers(new pcl::PointIndices); //inliers indicate the point where the error can be tolerated, and the sequence number of the point cloud is recorded |
| 118 | pcl::SACSegmentation<PointT> seg; // Create a splitter |
| 119 | seg.setOptimizeCoefficients(true); // Optional, this setting can choose whether the points displayed in the result plane are split points or the remaining points. |
| 120 | seg.setModelType(pcl::SACMODEL_LINE); // Mandatory-set the target geometry |
| 121 | seg.setMethodType(pcl::SAC_RANSAC); //Segmentation method: random sampling method |
| 122 | seg.setDistanceThreshold(0.25); //Set the error tolerance range, which is the threshold |
| 123 | seg.setInputCloud(tree); //Input point cloud |
| 124 | seg.segment(*inliers, *coefficients); //Split point cloud, get plane and normal vector |
| 125 | |
| 126 | if (inliers->indices.size() == 0) |
| 127 | { |
| 128 | ROS_DEBUG_STREAM("RANSAC Line Fitting failed"); |
| 129 | model.radius = -1; |
| 130 | return; |
| 131 | } |
| 132 |
nothing calls this directly
no outgoing calls
no test coverage detected