25 namespace mapping_3d {
26 namespace scan_matching {
30 constexpr
float kMinDistance = 0.2f;
31 constexpr
float kMaxDistance = 0.9f;
32 constexpr
float kSliceHeight = 0.2f;
34 void AddValueToHistogram(
float angle,
const float value,
35 Eigen::VectorXf* histogram) {
38 while (angle > static_cast<float>(M_PI)) {
39 angle -=
static_cast<float>(M_PI);
42 angle +=
static_cast<float>(M_PI);
44 const float zero_to_one = angle /
static_cast<float>(M_PI);
45 const int bucket = common::Clamp<int>(
47 histogram->size() - 1);
48 (*histogram)(bucket) += value;
52 CHECK(!slice.empty());
53 Eigen::Vector3f sum = Eigen::Vector3f::Zero();
54 for (
const Eigen::Vector3f& point : slice) {
57 return sum /
static_cast<float>(slice.size());
60 struct AngleValuePair {
65 void AddPointCloudSliceToValueVector(
67 std::vector<AngleValuePair>* value_vector) {
75 const Eigen::Vector3f centroid = ComputeCentroid(slice);
76 Eigen::Vector3f last_point = slice.front();
77 for (
const Eigen::Vector3f& point : slice) {
78 const Eigen::Vector2f delta = (point - last_point).head<2>();
79 const Eigen::Vector2f direction = (point - centroid).head<2>();
80 const float distance = delta.norm();
81 if (distance < kMinDistance || direction.norm() < kMinDistance) {
84 if (distance > kMaxDistance) {
89 const float value = std::max(
90 0.f, 1.f - std::abs(delta.normalized().dot(direction.normalized())));
91 value_vector->push_back(AngleValuePair{
angle, value});
99 struct SortableAnglePointPair {
100 bool operator<(
const SortableAnglePointPair& rhs)
const {
101 return angle < rhs.angle;
105 Eigen::Vector3f point;
107 const Eigen::Vector3f centroid = ComputeCentroid(slice);
108 std::vector<SortableAnglePointPair> by_angle;
109 by_angle.reserve(slice.size());
110 for (
const Eigen::Vector3f& point : slice) {
111 const Eigen::Vector2f delta = (point - centroid).head<2>();
112 if (delta.norm() < kMinDistance) {
115 by_angle.push_back(SortableAnglePointPair{
common::atan2(delta), point});
117 std::sort(by_angle.begin(), by_angle.end());
119 for (
const auto& pair : by_angle) {
120 result.push_back(pair.point);
125 std::vector<AngleValuePair> GetValuesForHistogram(
127 std::map<int, sensor::PointCloud> slices;
128 for (
const Eigen::Vector3f& point : point_cloud) {
131 std::vector<AngleValuePair> result;
132 for (
const auto& slice : slices) {
133 AddPointCloudSliceToValueVector(SortSlice(slice.second), &result);
138 void AddValuesToHistogram(
const std::vector<AngleValuePair>& value_vector,
139 const float rotation, Eigen::VectorXf* histogram) {
140 for (
const AngleValuePair& pair : value_vector) {
141 AddValueToHistogram(pair.angle + rotation, pair.value, histogram);
148 const std::vector<mapping::TrajectoryNode>& nodes,
const int histogram_size)
149 : histogram_(
Eigen::VectorXf::Zero(histogram_size)) {
151 AddValuesToHistogram(
153 node.constant_data->range_data_3d.returns.Decompress(),
154 node.pose.cast<
float>())),
161 const std::vector<float>& angles)
const {
162 std::vector<float> result;
163 result.reserve(angles.size());
164 const std::vector<AngleValuePair> value_vector =
165 GetValuesForHistogram(point_cloud);
166 for (
const float angle : angles) {
167 Eigen::VectorXf scan_histogram = Eigen::VectorXf::Zero(
histogram_.size());
168 AddValuesToHistogram(value_vector, angle, &scan_histogram);
175 const Eigen::VectorXf& scan_histogram)
const {
178 const float scan_histogram_norm = scan_histogram.norm();
179 const float histogram_norm =
histogram_.norm();
180 const float normalization = scan_histogram_norm * histogram_norm;
181 if (normalization < 1e-3f) {
184 return histogram_.dot(scan_histogram) / normalization;
PointCloud TransformPointCloud(const PointCloud &point_cloud, const transform::Rigid3f &transform)
RotationalScanMatcher(const std::vector< mapping::TrajectoryNode > &nodes, int histogram_size)
int RoundToInt(const float x)
T atan2(const Eigen::Matrix< T, 2, 1 > &vector)
Eigen::VectorXf histogram_
std::vector< Eigen::Vector3f > PointCloud
float MatchHistogram(const Eigen::VectorXf &scan_histogram) const
std::vector< float > Match(const sensor::PointCloud &point_cloud, const std::vector< float > &angles) const