Search code examples
point-cloud-library

What unit is `getFitnessScore()` in the IterativeClosestPoint class from PCL returning?


I use the pcl::IterativeClosestPoint method from the Point-Cloud-Library. As of right now it seems that the documentation of it is offline. Here in google cache. And also a tutorial.

There is a possibility to call icp.getFitnessScore() to get the mean squared distances from the points of the two clouds. I just can't find information on what kind of unit this is indicated. Does anyone knows what the number I get there means? For example output for me was: 0,0003192. This seems to be low, but I have no clue if it is meters, centimeters, feet, or whatever.

Thank you very much.


Solution

  • what kind of unit is icp.getFitnessScore() used?

    Like Joy said in his comment, the unit is the same as your input data.
    For example, your input point cloud might comes from a obj file. And a point will be stored like v 9.322 -1.0778 0.44997. The number returned by icp.getFitnessScore() will have the same unit as the point's coordinate.


    Does anyone knows what the number I get there means?

    The number you get represents the mean squared distance from each point in source to its closest point in target.

    That is to say, if you assume every point in source has a corresponding point in target, and the correspondence set comes from closest point data association, then the number represents the mean squared distance between all correspondences. That can be seen from the source code below.

    To make more sense of the function, you might want to filter out correspondences that have a large distance between them. (The two point cloud might only partially overlap.) And the function actually has an optional parameter max_range that does this.


    The method getFitnessScore() is defined in pcl::Registration, the base class of pcl::IterativeClosestPoint. The optional parameter max_range is defaulted to be std::numeric_limits<double>::max(), as you can see in the definition:

    /** \brief Obtain the Euclidean fitness score (e.g., sum of squared distances from the source to the target)
      * \param[in] max_range maximum allowable distance between a point and its correspondence in the target 
      * (default: double::max)
      */
    inline double 
    getFitnessScore (double max_range = std::numeric_limits<double>::max ());
    

    And the source code of this function is:

    template <typename PointSource, typename PointTarget, typename Scalar> inline double
    pcl::Registration<PointSource, PointTarget, Scalar>::getFitnessScore (double max_range)
    {
    
      double fitness_score = 0.0;
    
      // Transform the input dataset using the final transformation
      PointCloudSource input_transformed;
      transformPointCloud (*input_, input_transformed, final_transformation_);
    
      std::vector<int> nn_indices (1);
      std::vector<float> nn_dists (1);
    
      // For each point in the source dataset
      int nr = 0;
      for (size_t i = 0; i < input_transformed.points.size (); ++i)
      {
        // Find its nearest neighbor in the target
        tree_->nearestKSearch (input_transformed.points[i], 1, nn_indices, nn_dists);
    
        // Deal with occlusions (incomplete targets)
        if (nn_dists[0] <= max_range)
        {
          // Add to the fitness score
          fitness_score += nn_dists[0];
          nr++;
        } 
      } 
    
      if (nr > 0)
        return (fitness_score / nr);
      else
        return (std::numeric_limits<double>::max ());
    
    }