real_match_2d.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include "real_match_2d/real_match_2d.h"
  2. #include "filter/filter.h"
  3. namespace hlzn_slam {
  4. template <typename T>
  5. constexpr T Power(T base, int exponent) {
  6. return (exponent != 0) ? base * Power(base, exponent - 1) : T(1);
  7. }
  8. // Calculates a^2.
  9. template <typename T>
  10. constexpr T Pow2(T a) {
  11. return Power(a, 2);
  12. }
  13. RealTimeMatch2D::RealTimeMatch2D() : linear_range_(0.5),
  14. angle_range_(0.12),
  15. linear_step_(0.05),
  16. angle_step_(0.017)
  17. {
  18. transforms_ =
  19. __generateTransfroms(linear_range_, angle_range_, linear_step_, angle_step_);
  20. }
  21. void RealTimeMatch2D::setSearchRange(const float linear_range, const float angle_range, const float linear_step, const float angle_step)
  22. {
  23. linear_range_ = linear_range;
  24. angle_range_ = angle_range;
  25. linear_step_ = linear_step;
  26. angle_step_ = angle_step;
  27. transforms_ =
  28. __generateTransfroms(linear_range, angle_range, linear_step, angle_step);
  29. }
  30. float RealTimeMatch2D::match(const common::PointCloud& point_cloud,
  31. const common::Rigid2f& init_pose,
  32. common::Rigid2f& opt_pose,
  33. Map& map,
  34. bool use_smart)
  35. {
  36. std::vector<common::Rigid2f> transforms =
  37. __generateTransfroms(linear_range_, angle_range_, linear_step_, angle_step_);
  38. if (!use_smart) {
  39. return __match(point_cloud, init_pose, opt_pose, transforms, map);
  40. }
  41. return __smartMatch(point_cloud, init_pose, opt_pose, transforms, map);
  42. }
  43. float RealTimeMatch2D::towerMatch(const common::PointCloud& point_cloud, const common::Rigid2f& init_pose,
  44. common::Rigid2f& opt_pose, Map& map, const float multiple, bool use_smart)
  45. {
  46. const float linear_range = linear_range_;
  47. const float angle_range = angle_range_;
  48. const float linear_step = linear_step_;
  49. const float angle_step = angle_step_ * multiple;
  50. common::Rigid2f mid;
  51. std::vector<common::Rigid2f> transforms =
  52. __generateTransfroms(linear_range, angle_range, linear_step, angle_step);
  53. if (!use_smart) {
  54. __match(point_cloud, init_pose, mid, transforms, map);
  55. }
  56. else {
  57. __smartMatch(point_cloud, init_pose, mid, transforms, map);
  58. }
  59. transforms =
  60. __generateTransfroms(linear_step, angle_step, linear_step_, angle_step_);
  61. if (!use_smart) {
  62. return __match(point_cloud, mid, opt_pose, transforms, map);
  63. }
  64. return __smartMatch(point_cloud, mid, opt_pose, transforms, map);
  65. }
  66. float RealTimeMatch2D::__match(const common::PointCloud& point_cloud, const common::Rigid2f& init_pose,
  67. common::Rigid2f& opt_pose, const std::vector<common::Rigid2f>& transforms, Map& map)
  68. {
  69. float maxmal_cost = 0;
  70. // 滤波
  71. common::PointCloud filter = point_cloud;// filter::MapVoxelInterpolationFilter(point_cloud, map, map.getResolution());
  72. for (const common::Rigid2f& transform : transforms) {
  73. common::PointCloud trans_cloud =
  74. __transformPointCloud(filter, init_pose * transform);
  75. float cost = map.getCost(trans_cloud);
  76. // 对抗长直走廊,对抗激光点云过于稀疏
  77. cost *= std::exp(-Pow2((transform.translation().norm() * 1e-1 + fabs(transform.rotation().angle()) * 1e-1)));
  78. if (cost > maxmal_cost) {
  79. maxmal_cost = cost;
  80. opt_pose = init_pose * transform;
  81. }
  82. }
  83. // if (maxmal_cost < 1e-2) { // 0.01
  84. // return false;
  85. // }
  86. return maxmal_cost;
  87. }
  88. float RealTimeMatch2D::__smartMatch(const common::PointCloud& point_cloud,
  89. const common::Rigid2f& init_pose,
  90. common::Rigid2f& opt_pose,
  91. const std::vector<common::Rigid2f>& transforms,
  92. Map& map)
  93. {
  94. std::vector<common::PointCloud> group;
  95. common::PointCloud element;
  96. // 分组
  97. for (int i = 0;i < point_cloud.data.size();i++) {
  98. if (!element.data.empty()) {
  99. float dist = hypot(element.data.back()(0) - point_cloud.data[i](0),
  100. element.data.back()(1) - point_cloud.data[i](1));
  101. if (dist > 0.2 || i == point_cloud.data.size() - 1) {
  102. group.push_back(element);
  103. element.data.clear();
  104. }
  105. }
  106. element.data.push_back(point_cloud.data[i]);
  107. }
  108. common::PointCloud filter = point_cloud;// filter::MapVoxelInterpolationFilter(point_cloud, map, map.getResolution());
  109. float maxmal_cost = 0;
  110. // LOG(INFO)<<"size: "<<point_cloud.data.size()<<" size: "<<group.size();
  111. for (const common::Rigid2f& transform : transforms) {
  112. float cost = 0;
  113. for (common::PointCloud& element : group) {
  114. common::PointCloud trans_cloud =
  115. __transformPointCloud(element, init_pose * transform);
  116. cost += map.getCost(trans_cloud);
  117. }
  118. // 对抗长直走廊,对抗激光点云过于稀疏
  119. cost *= std::exp(-Pow2((transform.translation().norm() * 1e-1 + fabs(transform.rotation().angle()) * 1e-1)));
  120. if (cost > maxmal_cost) {
  121. maxmal_cost = cost;
  122. opt_pose = init_pose * transform;
  123. }
  124. }
  125. return maxmal_cost;
  126. }
  127. common::PointCloud RealTimeMatch2D::__transformPointCloud(
  128. const common::PointCloud& point_cloud, const common::Rigid2f& transform)
  129. {
  130. common::PointCloud trans_cloud;
  131. trans_cloud.data.resize(point_cloud.data.size());
  132. for (int i = 0;i < point_cloud.data.size();i++) {
  133. Eigen::Vector3f trans;
  134. common::Rigid2f::Vector vector = point_cloud.data[i].head<2>();
  135. vector = transform * vector;
  136. trans = Eigen::Vector3f(vector(0), vector(1), 0.0);
  137. trans_cloud.data[i] = trans;
  138. }
  139. trans_cloud.time = point_cloud.time;
  140. return trans_cloud;
  141. }
  142. std::vector<common::Rigid2f> RealTimeMatch2D::__generateTransfroms(const float linear_range,
  143. const float angle_range,
  144. const float linear_step,
  145. const float angle_step)
  146. {
  147. std::vector<common::Rigid2f> transforms;
  148. int linear_num = ceil(linear_range / linear_step) * 2;
  149. int angular_num = ceil(angle_range / angle_step) * 2;
  150. int size = linear_num * linear_num * angular_num;
  151. int i = 0;
  152. if (size < 1) {
  153. return transforms;
  154. }
  155. transforms.resize(size);
  156. for (int row = 0;row < linear_num;row++) {
  157. for (int col = 0;col < linear_num;col++) {
  158. float x = -linear_range + static_cast<float>(row * linear_step);
  159. float y = -linear_range + static_cast<float>(col * linear_step);
  160. Eigen::Matrix<float, 2, 1> translation(x, y);
  161. for (int a = 0;a < angular_num;a++) {
  162. float angle = -angle_range + static_cast<float>(a * angle_step);
  163. transforms[i++] = common::Rigid2f(translation, angle);
  164. }
  165. }
  166. }
  167. return transforms;
  168. }
  169. }