Program Listing for File ndt_omp.h

Return to documentation for file (include/pclomp/ndt_omp.h)

/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *  Copyright (c) 2012-, Open Perception, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the copyright holder(s) nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_REGISTRATION_NDT_OMP_H_
#define PCL_REGISTRATION_NDT_OMP_H_

#include <pcl/registration/registration.h>
#include <pcl/search/impl/search.hpp>
#include "voxel_grid_covariance_omp.h"

#include <unsupported/Eigen/NonLinearOptimization>

namespace pclomp
{
    enum NeighborSearchMethod {
        KDTREE,
        DIRECT26,
        DIRECT7,
        DIRECT1
    };

    template<typename PointSource, typename PointTarget>
    class NormalDistributionsTransform : public pcl::Registration<PointSource, PointTarget>
    {
    protected:

        typedef typename pcl::Registration<PointSource, PointTarget>::PointCloudSource PointCloudSource;
        typedef typename PointCloudSource::Ptr PointCloudSourcePtr;
        typedef typename PointCloudSource::ConstPtr PointCloudSourceConstPtr;

        typedef typename pcl::Registration<PointSource, PointTarget>::PointCloudTarget PointCloudTarget;
        typedef typename PointCloudTarget::Ptr PointCloudTargetPtr;
        typedef typename PointCloudTarget::ConstPtr PointCloudTargetConstPtr;

        typedef pcl::PointIndices::Ptr PointIndicesPtr;
        typedef pcl::PointIndices::ConstPtr PointIndicesConstPtr;

        typedef pclomp::VoxelGridCovariance<PointTarget> TargetGrid;
        typedef TargetGrid* TargetGridPtr;
        typedef const TargetGrid* TargetGridConstPtr;
        typedef typename TargetGrid::LeafConstPtr TargetGridLeafConstPtr;


    public:

#if PCL_VERSION >= PCL_VERSION_CALC(1, 10, 0)
        typedef pcl::shared_ptr< NormalDistributionsTransform<PointSource, PointTarget> > Ptr;
        typedef pcl::shared_ptr< const NormalDistributionsTransform<PointSource, PointTarget> > ConstPtr;
#else
        typedef boost::shared_ptr< NormalDistributionsTransform<PointSource, PointTarget> > Ptr;
        typedef boost::shared_ptr< const NormalDistributionsTransform<PointSource, PointTarget> > ConstPtr;
#endif


        NormalDistributionsTransform();

        virtual ~NormalDistributionsTransform() {}

    void setNumThreads(int n) {
      num_threads_ = n;
    }

        inline void
            setInputTarget(const PointCloudTargetConstPtr &cloud)
        {
            pcl::Registration<PointSource, PointTarget>::setInputTarget(cloud);
            init();
        }

        inline void
            setResolution(float resolution)
        {
            // Prevents unnecessary voxel initiations
            if (resolution_ != resolution)
            {
                resolution_ = resolution;
                if (input_)
                    init();
            }
        }

        inline float
            getResolution() const
        {
            return (resolution_);
        }

        inline double
            getStepSize() const
        {
            return (step_size_);
        }

        inline void
            setStepSize(double step_size)
        {
            step_size_ = step_size;
        }

        inline double
            getOutlierRatio() const
        {
            return (outlier_ratio_);
        }

        inline void
            setOutlierRatio(double outlier_ratio)
        {
            outlier_ratio_ = outlier_ratio;
        }

        inline void setNeighborhoodSearchMethod(NeighborSearchMethod method) {
            search_method = method;
        }

        inline double
            getTransformationProbability() const
        {
            return (trans_probability_);
        }

        inline int
            getFinalNumIteration() const
        {
            return (nr_iterations_);
        }

        static void
            convertTransform(const Eigen::Matrix<double, 6, 1> &x, Eigen::Affine3f &trans)
        {
            trans = Eigen::Translation<float, 3>(float(x(0)), float(x(1)), float(x(2))) *
                Eigen::AngleAxis<float>(float(x(3)), Eigen::Vector3f::UnitX()) *
                Eigen::AngleAxis<float>(float(x(4)), Eigen::Vector3f::UnitY()) *
                Eigen::AngleAxis<float>(float(x(5)), Eigen::Vector3f::UnitZ());
        }

        static void
            convertTransform(const Eigen::Matrix<double, 6, 1> &x, Eigen::Matrix4f &trans)
        {
            Eigen::Affine3f _affine;
            convertTransform(x, _affine);
            trans = _affine.matrix();
        }

        // negative log likelihood function
        // lower is better
        double calculateScore(const PointCloudSource& cloud) const;

    protected:

        using pcl::Registration<PointSource, PointTarget>::reg_name_;
        using pcl::Registration<PointSource, PointTarget>::getClassName;
        using pcl::Registration<PointSource, PointTarget>::input_;
        using pcl::Registration<PointSource, PointTarget>::indices_;
        using pcl::Registration<PointSource, PointTarget>::target_;
        using pcl::Registration<PointSource, PointTarget>::nr_iterations_;
        using pcl::Registration<PointSource, PointTarget>::max_iterations_;
        using pcl::Registration<PointSource, PointTarget>::previous_transformation_;
        using pcl::Registration<PointSource, PointTarget>::final_transformation_;
        using pcl::Registration<PointSource, PointTarget>::transformation_;
        using pcl::Registration<PointSource, PointTarget>::transformation_epsilon_;
        using pcl::Registration<PointSource, PointTarget>::converged_;
        using pcl::Registration<PointSource, PointTarget>::corr_dist_threshold_;
        using pcl::Registration<PointSource, PointTarget>::inlier_threshold_;

        using pcl::Registration<PointSource, PointTarget>::update_visualizer_;

        virtual void
            computeTransformation(PointCloudSource &output)
        {
            computeTransformation(output, Eigen::Matrix4f::Identity());
        }

        virtual void
            computeTransformation(PointCloudSource &output, const Eigen::Matrix4f &guess);

        void inline
            init()
        {
            target_cells_.setLeafSize(resolution_, resolution_, resolution_);
            target_cells_.setInputCloud(target_);
            // Initiate voxel structure.
            target_cells_.filter(true);
        }

        double
            computeDerivatives(Eigen::Matrix<double, 6, 1> &score_gradient,
                Eigen::Matrix<double, 6, 6> &hessian,
                PointCloudSource &trans_cloud,
                Eigen::Matrix<double, 6, 1> &p,
                bool compute_hessian = true);

        double
            updateDerivatives(Eigen::Matrix<double, 6, 1> &score_gradient,
                Eigen::Matrix<double, 6, 6> &hessian,
                const Eigen::Matrix<float, 4, 6> &point_gradient_,
                const Eigen::Matrix<float, 24, 6> &point_hessian_,
                const Eigen::Vector3d &x_trans, const Eigen::Matrix3d &c_inv,
                bool compute_hessian = true) const;

        void
            computeAngleDerivatives(Eigen::Matrix<double, 6, 1> &p, bool compute_hessian = true);

        void
            computePointDerivatives(Eigen::Vector3d &x, Eigen::Matrix<double, 3, 6>& point_gradient_, Eigen::Matrix<double, 18, 6>& point_hessian_, bool compute_hessian = true) const;

        void
            computePointDerivatives(Eigen::Vector3d &x, Eigen::Matrix<float, 4, 6>& point_gradient_, Eigen::Matrix<float, 24, 6>& point_hessian_, bool compute_hessian = true) const;

        void
            computeHessian(Eigen::Matrix<double, 6, 6> &hessian,
                PointCloudSource &trans_cloud,
                Eigen::Matrix<double, 6, 1> &p);

        void
            updateHessian(Eigen::Matrix<double, 6, 6> &hessian,
                const Eigen::Matrix<double, 3, 6> &point_gradient_,
                const Eigen::Matrix<double, 18, 6> &point_hessian_,
                const Eigen::Vector3d &x_trans, const Eigen::Matrix3d &c_inv) const;

        double
            computeStepLengthMT(const Eigen::Matrix<double, 6, 1> &x,
                Eigen::Matrix<double, 6, 1> &step_dir,
                double step_init,
                double step_max, double step_min,
                double &score,
                Eigen::Matrix<double, 6, 1> &score_gradient,
                Eigen::Matrix<double, 6, 6> &hessian,
                PointCloudSource &trans_cloud);

        bool
            updateIntervalMT(double &a_l, double &f_l, double &g_l,
                double &a_u, double &f_u, double &g_u,
                double a_t, double f_t, double g_t);

        double
            trialValueSelectionMT(double a_l, double f_l, double g_l,
                double a_u, double f_u, double g_u,
                double a_t, double f_t, double g_t);

        inline double
            auxiliaryFunction_PsiMT(double a, double f_a, double f_0, double g_0, double mu = 1.e-4)
        {
            return (f_a - f_0 - mu * g_0 * a);
        }

        inline double
            auxiliaryFunction_dPsiMT(double g_a, double g_0, double mu = 1.e-4)
        {
            return (g_a - mu * g_0);
        }

        TargetGrid target_cells_;

        //double fitness_epsilon_;

        float resolution_;

        double step_size_;

        double outlier_ratio_;

        double gauss_d1_, gauss_d2_, gauss_d3_;

        double trans_probability_;

        Eigen::Vector3d j_ang_a_, j_ang_b_, j_ang_c_, j_ang_d_, j_ang_e_, j_ang_f_, j_ang_g_, j_ang_h_;

        Eigen::Matrix<float, 8, 4> j_ang;

        Eigen::Vector3d h_ang_a2_, h_ang_a3_,
            h_ang_b2_, h_ang_b3_,
            h_ang_c2_, h_ang_c3_,
            h_ang_d1_, h_ang_d2_, h_ang_d3_,
            h_ang_e1_, h_ang_e2_, h_ang_e3_,
            h_ang_f1_, h_ang_f2_, h_ang_f3_;

        Eigen::Matrix<float, 16, 4> h_ang;

  //      Eigen::Matrix<double, 3, 6> point_gradient_;

  //      Eigen::Matrix<double, 18, 6> point_hessian_;

    int num_threads_;

    public:
        NeighborSearchMethod search_method;

        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
    };

}

#endif // PCL_REGISTRATION_NDT_H_