fast_vgicp_voxel.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #ifndef FAST_GICP_FAST_VGICP_VOXEL_HPP
  2. #define FAST_GICP_FAST_VGICP_VOXEL_HPP
  3. #include <unordered_map>
  4. #include <boost/functional/hash.hpp>
  5. #include "gicp_settings.hpp"
  6. namespace fast_gicp {
  7. static std::vector<Eigen::Vector3i, Eigen::aligned_allocator<Eigen::Vector3i>> neighbor_offsets(NeighborSearchMethod search_method) {
  8. switch(search_method) {
  9. // clang-format off
  10. default:
  11. std::cerr << "unsupported neighbor search method" << std::endl;
  12. abort();
  13. case NeighborSearchMethod::DIRECT1:
  14. return std::vector<Eigen::Vector3i, Eigen::aligned_allocator<Eigen::Vector3i>>{
  15. Eigen::Vector3i(0, 0, 0)
  16. };
  17. case NeighborSearchMethod::DIRECT7:
  18. return std::vector<Eigen::Vector3i, Eigen::aligned_allocator<Eigen::Vector3i>>{
  19. Eigen::Vector3i(0, 0, 0),
  20. Eigen::Vector3i(1, 0, 0),
  21. Eigen::Vector3i(-1, 0, 0),
  22. Eigen::Vector3i(0, 1, 0),
  23. Eigen::Vector3i(0, -1, 0),
  24. Eigen::Vector3i(0, 0, 1),
  25. Eigen::Vector3i(0, 0, -1)
  26. };
  27. case NeighborSearchMethod::DIRECT27:
  28. break;
  29. // clang-format on
  30. }
  31. std::vector<Eigen::Vector3i, Eigen::aligned_allocator<Eigen::Vector3i>> offsets27;
  32. for(int i = 0; i < 3; i++) {
  33. for(int j = 0; j < 3; j++) {
  34. for(int k = 0; k < 3; k++) {
  35. offsets27.push_back(Eigen::Vector3i(i - 1, j - 1, k - 1));
  36. }
  37. }
  38. }
  39. return offsets27;
  40. }
  41. class Vector3iHash {
  42. public:
  43. size_t operator()(const Eigen::Vector3i& x) const {
  44. size_t seed = 0;
  45. boost::hash_combine(seed, x[0]);
  46. boost::hash_combine(seed, x[1]);
  47. boost::hash_combine(seed, x[2]);
  48. return seed;
  49. }
  50. };
  51. struct GaussianVoxel {
  52. public:
  53. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  54. using Ptr = std::shared_ptr<GaussianVoxel>;
  55. GaussianVoxel() {
  56. num_points = 0;
  57. mean.setZero();
  58. cov.setZero();
  59. }
  60. virtual ~GaussianVoxel() {}
  61. virtual void append(const Eigen::Vector4d& mean_, const Eigen::Matrix4d& cov_) = 0;
  62. virtual void finalize() = 0;
  63. public:
  64. int num_points;
  65. Eigen::Vector4d mean;
  66. Eigen::Matrix4d cov;
  67. };
  68. struct MultiplicativeGaussianVoxel : GaussianVoxel {
  69. public:
  70. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  71. MultiplicativeGaussianVoxel() : GaussianVoxel() {}
  72. virtual ~MultiplicativeGaussianVoxel() {}
  73. virtual void append(const Eigen::Vector4d& mean_, const Eigen::Matrix4d& cov_) override {
  74. num_points++;
  75. Eigen::Matrix4d cov_inv = cov_;
  76. cov_inv(3, 3) = 1;
  77. cov_inv = cov_inv.inverse().eval();
  78. cov += cov_inv;
  79. mean += cov_inv * mean_;
  80. }
  81. virtual void finalize() override {
  82. cov(3, 3) = 1;
  83. mean[3] = 1;
  84. cov = cov.inverse().eval();
  85. mean = (cov * mean).eval();
  86. }
  87. };
  88. struct AdditiveGaussianVoxel : GaussianVoxel {
  89. public:
  90. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  91. AdditiveGaussianVoxel() : GaussianVoxel() {}
  92. virtual ~AdditiveGaussianVoxel() {}
  93. virtual void append(const Eigen::Vector4d& mean_, const Eigen::Matrix4d& cov_) override {
  94. num_points++;
  95. mean += mean_;
  96. cov += cov_;
  97. }
  98. virtual void finalize() override {
  99. mean /= num_points;
  100. cov /= num_points;
  101. }
  102. };
  103. template<typename PointT>
  104. class GaussianVoxelMap {
  105. public:
  106. GaussianVoxelMap(double resolution, VoxelAccumulationMode mode) : voxel_resolution_(resolution), voxel_mode_(mode) {}
  107. void create_voxelmap(const pcl::PointCloud<PointT>& cloud, const std::vector<Eigen::Matrix4d, Eigen::aligned_allocator<Eigen::Matrix4d>>& covs) {
  108. voxels_.clear();
  109. for(int i = 0; i < cloud.size(); i++) {
  110. Eigen::Vector3i coord = voxel_coord(cloud.at(i).getVector4fMap().template cast<double>());
  111. auto found = voxels_.find(coord);
  112. if(found == voxels_.end()) {
  113. GaussianVoxel::Ptr voxel;
  114. switch(voxel_mode_) {
  115. case VoxelAccumulationMode::ADDITIVE:
  116. case VoxelAccumulationMode::ADDITIVE_WEIGHTED:
  117. voxel = std::shared_ptr<AdditiveGaussianVoxel>(new AdditiveGaussianVoxel);
  118. break;
  119. case VoxelAccumulationMode::MULTIPLICATIVE:
  120. voxel = std::shared_ptr<MultiplicativeGaussianVoxel>(new MultiplicativeGaussianVoxel);
  121. break;
  122. }
  123. found = voxels_.insert(found, std::make_pair(coord, voxel));
  124. }
  125. auto& voxel = found->second;
  126. voxel->append(cloud.at(i).getVector4fMap().template cast<double>(), covs[i]);
  127. }
  128. for(auto& voxel : voxels_) {
  129. voxel.second->finalize();
  130. }
  131. }
  132. Eigen::Vector3i voxel_coord(const Eigen::Vector4d& x) const {
  133. return (x.array() / voxel_resolution_ - 0.5).floor().template cast<int>().template head<3>();
  134. }
  135. Eigen::Vector4d voxel_origin(const Eigen::Vector3i& coord) const {
  136. Eigen::Vector3d origin = (coord.template cast<double>().array() + 0.5) * voxel_resolution_;
  137. return Eigen::Vector4d(origin[0], origin[1], origin[2], 1.0f);
  138. }
  139. GaussianVoxel::Ptr lookup_voxel(const Eigen::Vector3i& coord) const {
  140. auto found = voxels_.find(coord);
  141. if(found == voxels_.end()) {
  142. return nullptr;
  143. }
  144. return found->second;
  145. }
  146. private:
  147. double voxel_resolution_;
  148. VoxelAccumulationMode voxel_mode_;
  149. using VoxelMap = std::unordered_map<Eigen::Vector3i, GaussianVoxel::Ptr, Vector3iHash, std::equal_to<Eigen::Vector3i>, Eigen::aligned_allocator<std::pair<const Eigen::Vector3i, GaussianVoxel::Ptr>>>;
  150. VoxelMap voxels_;
  151. };
  152. } // namespace fast_gicp
  153. #endif