#ifndef FAST_GICP_FAST_VGICP_CUDA_IMPL_HPP #define FAST_GICP_FAST_VGICP_CUDA_IMPL_HPP #include #include #include #include #include #include #include #include #include #include #include namespace fast_gicp { template FastVGICPCuda::FastVGICPCuda() : LsqRegistration() { this->reg_name_ = "FastVGICPCuda"; k_correspondences_ = 20; voxel_resolution_ = 1.0; regularization_method_ = RegularizationMethod::PLANE; neighbor_search_method_ = NearestNeighborMethod::CPU_PARALLEL_KDTREE; vgicp_cuda_.reset(new cuda::FastVGICPCudaCore()); vgicp_cuda_->set_resolution(voxel_resolution_); vgicp_cuda_->set_kernel_params(0.5, 3.0); } template FastVGICPCuda::~FastVGICPCuda() {} template void FastVGICPCuda::setCorrespondenceRandomness(int k) {} template void FastVGICPCuda::setResolution(double resolution) { vgicp_cuda_->set_resolution(resolution); } template void FastVGICPCuda::setKernelWidth(double kernel_width, double max_dist) { if (max_dist <= 0.0) { max_dist = kernel_width * 5.0; } vgicp_cuda_->set_kernel_params(kernel_width, max_dist); } template void FastVGICPCuda::setRegularizationMethod(RegularizationMethod method) { regularization_method_ = method; } template void FastVGICPCuda::setNeighborSearchMethod(NeighborSearchMethod method, double radius) { vgicp_cuda_->set_neighbor_search_method(method, radius); } template void FastVGICPCuda::setNearestNeighborSearchMethod(NearestNeighborMethod method) { neighbor_search_method_ = method; } template void FastVGICPCuda::swapSourceAndTarget() { vgicp_cuda_->swap_source_and_target(); input_.swap(target_); } template void FastVGICPCuda::clearSource() { input_.reset(); } template void FastVGICPCuda::clearTarget() { target_.reset(); } template void FastVGICPCuda::setInputSource(const PointCloudSourceConstPtr& cloud) { // the input cloud is the same as the previous one if(cloud == input_) { return; } pcl::Registration::setInputSource(cloud); std::vector> points(cloud->size()); std::transform(cloud->begin(), cloud->end(), points.begin(), [=](const PointSource& pt) { return pt.getVector3fMap(); }); vgicp_cuda_->set_source_cloud(points); switch(neighbor_search_method_) { case NearestNeighborMethod::CPU_PARALLEL_KDTREE: { std::vector neighbors = find_neighbors_parallel_kdtree(k_correspondences_, cloud); vgicp_cuda_->set_source_neighbors(k_correspondences_, neighbors); vgicp_cuda_->calculate_source_covariances(regularization_method_); } break; case NearestNeighborMethod::GPU_BRUTEFORCE: vgicp_cuda_->find_source_neighbors(k_correspondences_); vgicp_cuda_->calculate_source_covariances(regularization_method_); break; case NearestNeighborMethod::GPU_RBF_KERNEL: vgicp_cuda_->calculate_source_covariances_rbf(regularization_method_); break; } } template void FastVGICPCuda::setInputTarget(const PointCloudTargetConstPtr& cloud) { // the input cloud is the same as the previous one if(cloud == target_) { return; } pcl::Registration::setInputTarget(cloud); std::vector> points(cloud->size()); std::transform(cloud->begin(), cloud->end(), points.begin(), [=](const PointTarget& pt) { return pt.getVector3fMap(); }); vgicp_cuda_->set_target_cloud(points); switch(neighbor_search_method_) { case NearestNeighborMethod::CPU_PARALLEL_KDTREE: { std::vector neighbors = find_neighbors_parallel_kdtree(k_correspondences_, cloud); vgicp_cuda_->set_target_neighbors(k_correspondences_, neighbors); vgicp_cuda_->calculate_target_covariances(regularization_method_); } break; case NearestNeighborMethod::GPU_BRUTEFORCE: vgicp_cuda_->find_target_neighbors(k_correspondences_); vgicp_cuda_->calculate_target_covariances(regularization_method_); break; case NearestNeighborMethod::GPU_RBF_KERNEL: vgicp_cuda_->calculate_target_covariances_rbf(regularization_method_); break; } vgicp_cuda_->create_target_voxelmap(); } template void FastVGICPCuda::computeTransformation(PointCloudSource& output, const Matrix4& guess) { vgicp_cuda_->set_resolution(this->voxel_resolution_); LsqRegistration::computeTransformation(output, guess); } template template std::vector FastVGICPCuda::find_neighbors_parallel_kdtree(int k, typename pcl::PointCloud::ConstPtr cloud) const { pcl::search::KdTree kdtree; kdtree.setInputCloud(cloud); std::vector neighbors(cloud->size() * k); #pragma omp parallel for schedule(guided, 8) for(int i = 0; i < cloud->size(); i++) { std::vector k_indices; std::vector k_sq_distances; kdtree.nearestKSearch(cloud->at(i), k, k_indices, k_sq_distances); std::copy(k_indices.begin(), k_indices.end(), neighbors.begin() + i * k); } return neighbors; } template double FastVGICPCuda::linearize(const Eigen::Isometry3d& trans, Eigen::Matrix* H, Eigen::Matrix* b) { vgicp_cuda_->update_correspondences(trans); return vgicp_cuda_->compute_error(trans, H, b); } template double FastVGICPCuda::compute_error(const Eigen::Isometry3d& trans) { return vgicp_cuda_->compute_error(trans, nullptr, nullptr); } } // namespace fast_gicp #endif