Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <srs_env_model/but_server/plugins/octomap_plugin_tools/octomap_filter_ground.h>
00029 #include <pcl/sample_consensus/method_types.h>
00030 #include <pcl/sample_consensus/model_types.h>
00031 #include <pcl/segmentation/sac_segmentation.h>
00032 #include <pcl/filters/extract_indices.h>
00033 #include <pcl/filters/passthrough.h>
00034
00038 srs_env_model::COcFilterGround::COcFilterGround(const std::string & octree_frame_id, ERunMode mode )
00039 : COcTreeFilterBase(octree_frame_id,mode), m_numSpecRemoved(0)
00040 , m_inputPc(0)
00041 , m_groundPc(new tPointCloud)
00042 , m_nongroundPc(new tPointCloud)
00043 , m_groundFilterDistance(0.04)
00044 , m_groundFilterAngle(0.15)
00045 , m_groundFilterPlaneDistance(0.07)
00046 {
00047 assert(m_groundPc != 0 && m_nongroundPc != 0);
00048 }
00049
00053 void srs_env_model::COcFilterGround::setCloud(const tPointCloud * cloud)
00054 {
00055 assert(cloud != 0);
00056 m_inputPc = cloud;
00057 }
00058
00062 void srs_env_model::COcFilterGround::init(ros::NodeHandle & node_handle)
00063 {
00064
00065 node_handle.param("ocmap_ground_filter/distance", m_groundFilterDistance,
00066 m_groundFilterDistance);
00067
00068 node_handle.param("ocmap_ground_filter/angle", m_groundFilterAngle,
00069 m_groundFilterAngle);
00070
00071 node_handle.param("ocmap_ground_filter/plane_distance",
00072 m_groundFilterPlaneDistance, m_groundFilterPlaneDistance);
00073 }
00074
00078 void srs_env_model::COcFilterGround::filterInternal( tButServerOcTree & tree )
00079 {
00080 m_groundPc->header = m_inputPc->header;
00081 m_groundPc->header = m_inputPc->header;
00082
00083 if (m_inputPc->size() < 50)
00084 {
00085 ROS_WARN("Pointcloud in OctomapServer too small, skipping ground plane extraction");
00086 *m_nongroundPc = *m_inputPc;
00087 }
00088 else
00089 {
00090
00091 pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
00092 pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
00093
00094
00095 pcl::SACSegmentation<tPclPoint> seg;
00096 seg.setOptimizeCoefficients(true);
00097
00098 seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);
00099 seg.setMethodType(pcl::SAC_RANSAC);
00100 seg.setMaxIterations(200);
00101 seg.setDistanceThreshold(m_groundFilterDistance);
00102 seg.setAxis(Eigen::Vector3f(0, 0, 1));
00103 seg.setEpsAngle(m_groundFilterAngle);
00104
00105 tPointCloud cloud_filtered(*m_inputPc);
00106
00107 pcl::ExtractIndices<tPclPoint> extract;
00108 bool groundPlaneFound = false;
00109
00110 while (cloud_filtered.size() > 10 && !groundPlaneFound) {
00111 seg.setInputCloud(cloud_filtered.makeShared());
00112 seg.segment(*inliers, *coefficients);
00113 if (inliers->indices.size() == 0) {
00114 ROS_WARN("No plane found in cloud.");
00115
00116 break;
00117 }
00118
00119 extract.setInputCloud(cloud_filtered.makeShared());
00120 extract.setIndices(inliers);
00121
00122 if (std::abs(coefficients->values.at(3))
00123 < m_groundFilterPlaneDistance) {
00124 ROS_DEBUG("Ground plane found: %zu/%zu inliers. Coeff: %f %f %f %f", inliers->indices.size(),
00125 cloud_filtered.size(), coefficients->values.at(0), coefficients->values.at(1),
00126 coefficients->values.at(2), coefficients->values.at(3));
00127 extract.setNegative(false);
00128 extract.filter(*m_groundPc);
00129
00130
00131
00132 if (inliers->indices.size() != cloud_filtered.size()) {
00133 extract.setNegative(true);
00134 tPointCloud cloud_out;
00135 extract.filter(cloud_out);
00136 *m_nongroundPc += cloud_out;
00137 cloud_filtered = cloud_out;
00138 }
00139
00140 groundPlaneFound = true;
00141 } else {
00142 ROS_DEBUG("Horizontal plane (not ground) found: %zu/%zu inliers. Coeff: %f %f %f %f", inliers->indices.size(),
00143 cloud_filtered.size(), coefficients->values.at(0), coefficients->values.at(1),
00144 coefficients->values.at(2), coefficients->values.at(3));
00145 tPointCloud cloud_out;
00146 extract.setNegative(false);
00147 extract.filter(cloud_out);
00148 *m_nongroundPc += cloud_out;
00149
00150
00151
00152
00153
00154
00155 if (inliers->indices.size() != cloud_filtered.size()) {
00156 extract.setNegative(true);
00157 cloud_out.points.clear();
00158 extract.filter(cloud_out);
00159 cloud_filtered = cloud_out;
00160 } else {
00161 cloud_filtered.points.clear();
00162 }
00163 }
00164
00165 }
00166
00167 if (!groundPlaneFound) {
00168 ROS_WARN("No ground plane found in scan");
00169
00170
00171 pcl::PassThrough<tPclPoint> second_pass;
00172 second_pass.setFilterFieldName("z");
00173 second_pass.setFilterLimits(-m_groundFilterPlaneDistance,
00174 m_groundFilterPlaneDistance);
00175 second_pass.setInputCloud(m_inputPc->makeShared());
00176 second_pass.filter(*m_groundPc);
00177
00178 second_pass.setFilterLimitsNegative(true);
00179 second_pass.filter(*m_nongroundPc);
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189 }
00190 }
srs_env_model
Author(s): Vit Stancl (stancl@fit.vutbr.cz), Tomas Lokaj, Jan Gorig, Michal Spanel (spanel@fit.vutbr.cz)
autogenerated on Sun Jan 5 2014 11:50:48