Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "cartographer/mapping/internal/2d/scan_matching/correlative_scan_matcher_2d.h"
00018
00019 #include <cmath>
00020
00021 #include "cartographer/common/math.h"
00022
00023 namespace cartographer {
00024 namespace mapping {
00025 namespace scan_matching {
00026
00027 SearchParameters::SearchParameters(const double linear_search_window,
00028 const double angular_search_window,
00029 const sensor::PointCloud& point_cloud,
00030 const double resolution)
00031 : resolution(resolution) {
00032
00033
00034 float max_scan_range = 3.f * resolution;
00035 for (const sensor::RangefinderPoint& point : point_cloud) {
00036 const float range = point.position.head<2>().norm();
00037 max_scan_range = std::max(range, max_scan_range);
00038 }
00039 const double kSafetyMargin = 1. - 1e-3;
00040 angular_perturbation_step_size =
00041 kSafetyMargin * std::acos(1. - common::Pow2(resolution) /
00042 (2. * common::Pow2(max_scan_range)));
00043 num_angular_perturbations =
00044 std::ceil(angular_search_window / angular_perturbation_step_size);
00045 num_scans = 2 * num_angular_perturbations + 1;
00046
00047 const int num_linear_perturbations =
00048 std::ceil(linear_search_window / resolution);
00049 linear_bounds.reserve(num_scans);
00050 for (int i = 0; i != num_scans; ++i) {
00051 linear_bounds.push_back(
00052 LinearBounds{-num_linear_perturbations, num_linear_perturbations,
00053 -num_linear_perturbations, num_linear_perturbations});
00054 }
00055 }
00056
00057 SearchParameters::SearchParameters(const int num_linear_perturbations,
00058 const int num_angular_perturbations,
00059 const double angular_perturbation_step_size,
00060 const double resolution)
00061 : num_angular_perturbations(num_angular_perturbations),
00062 angular_perturbation_step_size(angular_perturbation_step_size),
00063 resolution(resolution),
00064 num_scans(2 * num_angular_perturbations + 1) {
00065 linear_bounds.reserve(num_scans);
00066 for (int i = 0; i != num_scans; ++i) {
00067 linear_bounds.push_back(
00068 LinearBounds{-num_linear_perturbations, num_linear_perturbations,
00069 -num_linear_perturbations, num_linear_perturbations});
00070 }
00071 }
00072
00073 void SearchParameters::ShrinkToFit(const std::vector<DiscreteScan2D>& scans,
00074 const CellLimits& cell_limits) {
00075 CHECK_EQ(scans.size(), num_scans);
00076 CHECK_EQ(linear_bounds.size(), num_scans);
00077 for (int i = 0; i != num_scans; ++i) {
00078 Eigen::Array2i min_bound = Eigen::Array2i::Zero();
00079 Eigen::Array2i max_bound = Eigen::Array2i::Zero();
00080 for (const Eigen::Array2i& xy_index : scans[i]) {
00081 min_bound = min_bound.min(-xy_index);
00082 max_bound = max_bound.max(Eigen::Array2i(cell_limits.num_x_cells - 1,
00083 cell_limits.num_y_cells - 1) -
00084 xy_index);
00085 }
00086 linear_bounds[i].min_x = std::max(linear_bounds[i].min_x, min_bound.x());
00087 linear_bounds[i].max_x = std::min(linear_bounds[i].max_x, max_bound.x());
00088 linear_bounds[i].min_y = std::max(linear_bounds[i].min_y, min_bound.y());
00089 linear_bounds[i].max_y = std::min(linear_bounds[i].max_y, max_bound.y());
00090 }
00091 }
00092
00093 std::vector<sensor::PointCloud> GenerateRotatedScans(
00094 const sensor::PointCloud& point_cloud,
00095 const SearchParameters& search_parameters) {
00096 std::vector<sensor::PointCloud> rotated_scans;
00097 rotated_scans.reserve(search_parameters.num_scans);
00098
00099 double delta_theta = -search_parameters.num_angular_perturbations *
00100 search_parameters.angular_perturbation_step_size;
00101 for (int scan_index = 0; scan_index < search_parameters.num_scans;
00102 ++scan_index,
00103 delta_theta += search_parameters.angular_perturbation_step_size) {
00104 rotated_scans.push_back(sensor::TransformPointCloud(
00105 point_cloud, transform::Rigid3f::Rotation(Eigen::AngleAxisf(
00106 delta_theta, Eigen::Vector3f::UnitZ()))));
00107 }
00108 return rotated_scans;
00109 }
00110
00111 std::vector<DiscreteScan2D> DiscretizeScans(
00112 const MapLimits& map_limits, const std::vector<sensor::PointCloud>& scans,
00113 const Eigen::Translation2f& initial_translation) {
00114 std::vector<DiscreteScan2D> discrete_scans;
00115 discrete_scans.reserve(scans.size());
00116 for (const sensor::PointCloud& scan : scans) {
00117 discrete_scans.emplace_back();
00118 discrete_scans.back().reserve(scan.size());
00119 for (const sensor::RangefinderPoint& point : scan) {
00120 const Eigen::Vector2f translated_point =
00121 Eigen::Affine2f(initial_translation) * point.position.head<2>();
00122 discrete_scans.back().push_back(
00123 map_limits.GetCellIndex(translated_point));
00124 }
00125 }
00126 return discrete_scans;
00127 }
00128
00129 }
00130 }
00131 }