2019-02-24 点云的曲面法向量估计

2019-02-26  本文已影响0人  韦德爱老詹

使用拟合方法求取局部点云法向量,可使用PCA方法,如:https://blog.csdn.net/eric_e/article/details/82190616
或使用SVD方法,如https://www.cnblogs.com/houkai/p/6656894.html
最小二乘法的求取方法:


法向量求解的6种方法:
void FiltersDemo::VectorscomputeWithAreaplaneSVD(grid_map::GridMap& map, const std::string& inputLayer, const std::string& outputLayersPrefix)
{
  // For each cell in requested area.
  int filter_cells = 0;
  ros::Time begin_time = ros::Time::now ();
  for (GridMapIterator iterator(map);!iterator.isPastEnd(); ++iterator) {
    // Check if this is an empty cell (hole in the map).
    
    if (!map.isValid(*iterator, inputLayer_)) continue;
    filter_cells ++;
    // Requested position (center) of circle in map.
    Position center;
    map.getPosition(*iterator, center);

    // Prepare data computation.
    const int maxNumberOfCells = pow(ceil(2 * estimationRadius_ / map.getResolution()), 2);
    Eigen::MatrixXd points(maxNumberOfCells, 3);

    // Gather surrounding data.
    size_t nPoints = 0;
    for (CircleIterator iterator(map, center, estimationRadius_); !iterator.isPastEnd(); ++iterator) {
      if (!map.isValid(*iterator, inputLayer_)) continue;
      Position3 point;
      map.getPosition3(inputLayer_, *iterator, point);
      points.row(nPoints) = point;
      nPoints++;
    }

    points.conservativeResize(nPoints, 3); // TODO Eigen version?
    Eigen::MatrixXd NN(nPoints, 4);
    NN.leftCols(3) = points;
    NN.rightCols(1).setOnes();
    // Compute Eigenvectors.
    
    if (nPoints < 4) continue;
  
    //std::cout << " **" << NN <<std::endl;
    JacobiSVD<Eigen::MatrixXd> svd(NN, ComputeThinU | ComputeThinV );
      
    
    Matrix4d V = svd.matrixV();
    //std::cout << "--" <<V << std::endl;
    
    Vector3 eigenvector;
    eigenvector.x() = V(0,3);
    eigenvector.y() = V(1,3);
    eigenvector.z() = V(2,3);
    
    if (eigenvector.dot(normalVectorPositiveAxis_) < 0.0) eigenvector = -eigenvector;
    map.at(outputLayersPrefix_ + "x", *iterator) = eigenvector.x();
    map.at(outputLayersPrefix_ + "y", *iterator) = eigenvector.y();
    map.at(outputLayersPrefix_ + "z", *iterator) = eigenvector.z();
      
  }
  std::cout << "filtercells_num:"<<filter_cells<<std::endl;
  double t1;
  t1 = (ros::Time::now () - begin_time).toSec ();
  std::cout << "method1 SVD filter time is:" << t1 << std::endl; 
}

void FiltersDemo::VectorscomputeWithAreaplaneSVDeigenvalue(grid_map::GridMap& map, const std::string& inputLayer, const std::string& outputLayersPrefix)
{
  // For each cell in requested area.
  int filter_cells = 0;
  ros::Time begin_time = ros::Time::now ();
  for (GridMapIterator iterator(map);!iterator.isPastEnd(); ++iterator) {
    // Check if this is an empty cell (hole in the map).
    
    if (!map.isValid(*iterator, inputLayer_)) continue;
    filter_cells ++;
    // Requested position (center) of circle in map.
    Position center;
    map.getPosition(*iterator, center);

    // Prepare data computation.
    const int maxNumberOfCells = pow(ceil(2 * estimationRadius_ / map.getResolution()), 2);
    Eigen::MatrixXd points(maxNumberOfCells, 3);

    // Gather surrounding data.
    size_t nPoints = 0;
    for (CircleIterator iterator(map, center, estimationRadius_); !iterator.isPastEnd(); ++iterator) {
      if (!map.isValid(*iterator, inputLayer_)) continue;
      Position3 point;
      map.getPosition3(inputLayer_, *iterator, point);
      points.row(nPoints) = point;
      nPoints++;
    }

    points.conservativeResize(nPoints, 3); // TODO Eigen version?
    Eigen::MatrixXd NN(nPoints, 4);
    NN.leftCols(3) = points;
    NN.rightCols(1).setOnes();
    // Compute Eigenvectors.
    
    if (nPoints < 4) continue;
  
    //std::cout << " **" << NN <<std::endl;
    const Eigen::Matrix4d covarianceMatrix(NN.transpose()*NN);
    Vector4d eigenvalues = Vector4d::Ones();
    Eigen::Matrix4d eigenvectors = Eigen::Matrix4d::Identity();
    // Ensure that the matrix is suited for eigenvalues calculation.
    const Eigen::EigenSolver<Eigen::MatrixXd> solver(covarianceMatrix);
    eigenvalues = solver.eigenvalues().real();
    eigenvectors = solver.eigenvectors().real();
    
    // Keep the smallest Eigenvector as normal vector.
    int smallestId(0);
    double smallestValue(std::numeric_limits<double>::max());
    for (int j = 0; j < eigenvectors.cols(); j++) {
      if (eigenvalues(j) < smallestValue) {
        smallestId = j;
        smallestValue = eigenvalues(j);
      }
    }
    Vector4d eigenvector = eigenvectors.col(smallestId);
    
    if (eigenvector.z() < 0.0) eigenvector = -eigenvector;
    map.at(outputLayersPrefix_ + "x", *iterator) = eigenvector.x();
    map.at(outputLayersPrefix_ + "y", *iterator) = eigenvector.y();
    map.at(outputLayersPrefix_ + "z", *iterator) = eigenvector.z();
      
  }
  std::cout << "filtercells_num:"<<filter_cells<<std::endl;
  double t1;
  t1 = (ros::Time::now () - begin_time).toSec ();
  std::cout << "method1 PAC filter time is:" << t1 << std::endl; 
}

void FiltersDemo::VectorscomputeWithAreaSVD(grid_map::GridMap& map, const std::string& inputLayer, const std::string& outputLayersPrefix)
{
  // For each cell in requested area.
  int filter_cells = 0;
  ros::Time begin_time = ros::Time::now ();
  for (GridMapIterator iterator(map);!iterator.isPastEnd(); ++iterator) {
    // Check if this is an empty cell (hole in the map).
    
    if (!map.isValid(*iterator, inputLayer_)) continue;
    filter_cells ++;
    // Requested position (center) of circle in map.
    Position center;
    map.getPosition(*iterator, center);

    // Prepare data computation.
    const int maxNumberOfCells = pow(ceil(2 * estimationRadius_ / map.getResolution()), 2);
    Eigen::MatrixXd points(maxNumberOfCells, 3);

    // Gather surrounding data.
    size_t nPoints = 0;
    for (CircleIterator iterator(map, center, estimationRadius_); !iterator.isPastEnd(); ++iterator) {
      if (!map.isValid(*iterator, inputLayer_)) continue;
      Position3 point;
      map.getPosition3(inputLayer_, *iterator, point);
      if(center.x() != point.x() && center.y() != point.y())
      {
        points.row(nPoints) = point;
        nPoints++;
      }
    }

    points.conservativeResize(nPoints, 3); // TODO Eigen version?
    //points.bottomRows(1).setOnes();
    // Compute Eigenvectors.

    if (nPoints < 4) continue;
    double smooth_height = points.rightCols(1).sum() / nPoints;
    double height = map.at(inputLayer_, *iterator);

    Position3 center3d;
    center3d.x() = center.x();
    center3d.y() = center.y();
    center3d.z() = height;
    Eigen::MatrixXd NN = points.bottomRows(nPoints).rowwise() - center3d.transpose();
     
    //std::cout << " **" << points <<std::endl;
    //std::cout << smooth_height << std::endl;
    JacobiSVD<Eigen::MatrixXd> svd(NN, ComputeThinU | ComputeThinV );
      
    Matrix3d V = svd.matrixV();
    
    Vector3 eigenvector = V.rightCols(1);
    if (eigenvector.dot(normalVectorPositiveAxis_) < 0.0) eigenvector = -eigenvector;

    /*
    double roughness = fabs(height - smooth_height);
    
    double slope = acos(eigenvector.z());
    
    double traversability = 0.5 * (1.0 - (slope / 0.6)) + 0.5 * (1.0 - (roughness / 0.1));
    */
    map.at(outputLayersPrefix_ + "x", *iterator) = eigenvector.x();
    map.at(outputLayersPrefix_ + "y", *iterator) = eigenvector.y();
    map.at(outputLayersPrefix_ + "z", *iterator) = eigenvector.z();

    /*
    map.at("Roughness", *iterator) = roughness;
    map.at("slope", *iterator) = slope;
    map.at("traversability", *iterator) = traversability;
    */

    
  }

  std::cout << "filtercells_num:"<<filter_cells<<std::endl;
  double t1;
  t1 = (ros::Time::now () - begin_time).toSec ();
  std::cout << "method3 SVD filter time is:" << t1 << std::endl; 
}

void FiltersDemo::VectorscomputeWithAreaeigenValue(grid_map::GridMap& map, const std::string& inputLayer, const std::string& outputLayersPrefix)
{
  // For each cell in requested area.
  int filter_cells = 0;
  ros::Time begin_time = ros::Time::now ();
  for (GridMapIterator iterator(map);!iterator.isPastEnd(); ++iterator) {
    // Check if this is an empty cell (hole in the map).
    
    if (!map.isValid(*iterator, inputLayer_)) continue;
    filter_cells ++;
    // Requested position (center) of circle in map.
    Position center;
    map.getPosition(*iterator, center);

    // Prepare data computation.
    const int maxNumberOfCells = pow(ceil(2 * estimationRadius_ / map.getResolution()), 2);
    Eigen::MatrixXd points(maxNumberOfCells, 3);

    // Gather surrounding data.
    size_t nPoints = 0;
    for (CircleIterator iterator(map, center, estimationRadius_); !iterator.isPastEnd(); ++iterator) {
      if (!map.isValid(*iterator, inputLayer_)) continue;
      Position3 point;
      map.getPosition3(inputLayer_, *iterator, point);
      if(center.x() != point.x() && center.y() != point.y())
      {
        points.row(nPoints) = point;
        nPoints++;
      }
    }
    
    points.conservativeResize(nPoints, 3); // TODO Eigen version?
    //points.bottomRows(1).setOnes();
    // Compute Eigenvectors.

    if (nPoints < 4) continue;
    double smooth_height = points.rightCols(1).sum() / nPoints;
    double height = map.at(inputLayer_, *iterator);

    Position3 center3d;
    center3d.x() = center.x();
    center3d.y() = center.y();
    center3d.z() = height;
    Eigen::MatrixXd NN = points.bottomRows(nPoints).rowwise() - center3d.transpose();

    const Eigen::Matrix3d covarianceMatrix(NN.transpose()*NN);
    Vector3 eigenvalues = Vector3::Ones();
    Eigen::Matrix3d eigenvectors = Eigen::Matrix3d::Identity();
    // Ensure that the matrix is suited for eigenvalues calculation.
    const Eigen::EigenSolver<Eigen::MatrixXd> solver(covarianceMatrix);
    eigenvalues = solver.eigenvalues().real();
    eigenvectors = solver.eigenvectors().real();
    
    // Keep the smallest Eigenvector as normal vector.
    int smallestId(0);
    double smallestValue(std::numeric_limits<double>::max());
    for (int j = 0; j < eigenvectors.cols(); j++) {
      if (eigenvalues(j) < smallestValue) {
        smallestId = j;
        smallestValue = eigenvalues(j);
      }
    }
    Vector3 eigenvector = eigenvectors.col(smallestId);
    if (eigenvector.dot(normalVectorPositiveAxis_) < 0.0) eigenvector = -eigenvector;
    /*
    double height = map.at(inputLayer_, *iterator);
    double smooth_height = mean.z();
    double roughness = fabs(height - smooth_height);
    
    double slope = acos(eigenvector.z());
    
    double traversability = 0.5 * (1.0 - (slope / 0.6)) + 0.5 * (1.0 - (roughness / 0.1));
    */
    map.at(outputLayersPrefix_ + "x", *iterator) = eigenvector.x();
    map.at(outputLayersPrefix_ + "y", *iterator) = eigenvector.y();
    map.at(outputLayersPrefix_ + "z", *iterator) = eigenvector.z();

    /*
    map.at("Roughness", *iterator) = roughness;
    map.at("slope", *iterator) = slope;
    map.at("traversability", *iterator) = traversability;
    */
  }
  std::cout << "filtercells_num:"<<filter_cells<<std::endl;
  double t1;
  t1 = (ros::Time::now () - begin_time).toSec ();
  std::cout << "method3 PAC filter time is:" << t1 << std::endl; 
}


void FiltersDemo::VectorscomputeWithArea(grid_map::GridMap& map, const std::string& inputLayer, const std::string& outputLayersPrefix)
{
  // For each cell in requested area.
  int filter_cells = 0;
  ros::Time begin_time = ros::Time::now ();
  for (GridMapIterator iterator(map);!iterator.isPastEnd(); ++iterator) {
    // Check if this is an empty cell (hole in the map).
    
    if (!map.isValid(*iterator, inputLayer_)) continue;
    filter_cells ++;
    // Requested position (center) of circle in map.
    Position center;
    map.getPosition(*iterator, center);

    // Prepare data computation.
    const int maxNumberOfCells = pow(ceil(2 * estimationRadius_ / map.getResolution()), 2);
    Eigen::MatrixXd points(3, maxNumberOfCells);

    // Gather surrounding data.
    size_t nPoints = 0;
    for (CircleIterator iterator(map, center, estimationRadius_); !iterator.isPastEnd(); ++iterator) {
      if (!map.isValid(*iterator, inputLayer_)) continue;
      Position3 point;
      map.getPosition3(inputLayer_, *iterator, point);
      points.col(nPoints) = point;
      nPoints++;
    }
    if (nPoints < 4) continue;
    points.conservativeResize(3, nPoints); // TODO Eigen version?

    // Compute Eigenvectors.
    
    const Position3 mean = points.leftCols(nPoints).rowwise().sum() / nPoints;
    const Eigen::MatrixXd NN = points.leftCols(nPoints).colwise() - mean;
    const Eigen::Matrix3d covarianceMatrix(NN * NN.transpose());
    Vector3 eigenvalues = Vector3::Ones();
    Eigen::Matrix3d eigenvectors = Eigen::Matrix3d::Identity();
    // Ensure that the matrix is suited for eigenvalues calculation.
    const Eigen::EigenSolver<Eigen::MatrixXd> solver(covarianceMatrix);
    eigenvalues = solver.eigenvalues().real();
    eigenvectors = solver.eigenvectors().real();
    
    // Keep the smallest Eigenvector as normal vector.
    int smallestId(0);
    double smallestValue(std::numeric_limits<double>::max());
    for (int j = 0; j < eigenvectors.cols(); j++) {
      if (eigenvalues(j) < smallestValue) {
        smallestId = j;
        smallestValue = eigenvalues(j);
      }
    }
    Vector3 eigenvector = eigenvectors.col(smallestId);
    if (eigenvector.dot(normalVectorPositiveAxis_) < 0.0) eigenvector = -eigenvector;
    /*
    double height = map.at(inputLayer_, *iterator);
    double smooth_height = mean.z();
    double roughness = fabs(height - smooth_height);
    
    double slope = acos(eigenvector.z());
    
    double traversability = 0.5 * (1.0 - (slope / 0.6)) + 0.5 * (1.0 - (roughness / 0.1));
    */
    map.at(outputLayersPrefix_ + "x", *iterator) = eigenvector.x();
    map.at(outputLayersPrefix_ + "y", *iterator) = eigenvector.y();
    map.at(outputLayersPrefix_ + "z", *iterator) = eigenvector.z();

    /*
    map.at("Roughness", *iterator) = roughness;
    map.at("slope", *iterator) = slope;
    map.at("traversability", *iterator) = traversability;
    */
  }
  std::cout << "filtercells_num:"<<filter_cells<<std::endl;
  double t1;
  t1 = (ros::Time::now () - begin_time).toSec ();
  std::cout << "method2 PAC filter time is:" << t1 << std::endl; 
}

void FiltersDemo::VectorscomputeWithArea_SVD(grid_map::GridMap& map, const std::string& inputLayer, const std::string& outputLayersPrefix)
{
  // For each cell in requested area.
  int filter_cells = 0;
  ros::Time begin_time = ros::Time::now ();
  for (GridMapIterator iterator(map);!iterator.isPastEnd(); ++iterator) {
    // Check if this is an empty cell (hole in the map).
    
    if (!map.isValid(*iterator, inputLayer_)) continue;
    filter_cells ++;
    // Requested position (center) of circle in map.
    Position center;
    map.getPosition(*iterator, center);

    // Prepare data computation.
    const int maxNumberOfCells = pow(ceil(2 * estimationRadius_ / map.getResolution()), 2);
    Eigen::MatrixXd points(3, maxNumberOfCells);

    // Gather surrounding data.
    size_t nPoints = 0;
    for (CircleIterator iterator(map, center, estimationRadius_); !iterator.isPastEnd(); ++iterator) {
      if (!map.isValid(*iterator, inputLayer_)) continue;
      Position3 point;
      map.getPosition3(inputLayer_, *iterator, point);
      points.col(nPoints) = point;
      nPoints++;
    }
    if (nPoints < 4) continue;
    points.conservativeResize(3, nPoints); // TODO Eigen version?
    // Compute Eigenvectors.
    
    const Position3 mean = points.leftCols(nPoints).rowwise().sum() / nPoints;
    const Eigen::MatrixXd NN = points.leftCols(nPoints).colwise() - mean;

    JacobiSVD<Eigen::MatrixXd> svd(NN.transpose(), ComputeThinU | ComputeThinV );
      
    Matrix3d V = svd.matrixV();
    Vector3 eigenvector = V.rightCols(1);

    if (eigenvector.dot(normalVectorPositiveAxis_) < 0.0) eigenvector = -eigenvector;
    
    double height = map.at(inputLayer_, *iterator);
    double smooth_height = mean.z();
    double roughness = fabs(height - smooth_height);
    
    double slope = acos(eigenvector.z());
    
    double traversability = 0.5 * (1.0 - (slope / 0.6)) + 0.5 * (1.0 - (roughness / 0.1));
    
    map.at(outputLayersPrefix_ + "x", *iterator) = eigenvector.x();
    map.at(outputLayersPrefix_ + "y", *iterator) = eigenvector.y();
    map.at(outputLayersPrefix_ + "z", *iterator) = eigenvector.z();

    
    map.at("Roughness", *iterator) = roughness;
    map.at("slope", *iterator) = slope;
    map.at("traversability", *iterator) = traversability;
    
  }
  std::cout << "filtercells_num:"<<filter_cells<<std::endl;
  double t1;
  t1 = (ros::Time::now () - begin_time).toSec ();
  std::cout << "method2 SVD filter time is:" << t1 << std::endl; 
}
上一篇 下一篇

猜你喜欢

热点阅读