Skip to content

Commit

Permalink
Keep intensities in the voxel filter. (#1764)
Browse files Browse the repository at this point in the history
Signed-off-by: Wolfgang Hess <whess@lyft.com>
  • Loading branch information
wohe committed Oct 19, 2020
1 parent 952f59d commit d3473fc
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
35 changes: 31 additions & 4 deletions cartographer/sensor/internal/voxel_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ VoxelKeyType GetVoxelCellIndex(const Eigen::Vector3f& point,
}

template <class T, class PointFunction>
std::vector<T> RandomizedVoxelFilter(const std::vector<T>& point_cloud,
const float resolution,
PointFunction&& point_function) {
std::vector<bool> RandomizedVoxelFilterIndices(
const std::vector<T>& point_cloud, const float resolution,
PointFunction&& point_function) {
// According to https://en.wikipedia.org/wiki/Reservoir_sampling
std::minstd_rand0 generator;
absl::flat_hash_map<VoxelKeyType, std::pair<int, int>>
Expand All @@ -110,6 +110,15 @@ std::vector<T> RandomizedVoxelFilter(const std::vector<T>& point_cloud,
for (const auto& voxel_and_index : voxel_count_and_point_index) {
points_used[voxel_and_index.second.second] = true;
}
return points_used;
}

template <class T, class PointFunction>
std::vector<T> RandomizedVoxelFilter(const std::vector<T>& point_cloud,
const float resolution,
PointFunction&& point_function) {
const std::vector<bool> points_used =
RandomizedVoxelFilterIndices(point_cloud, resolution, point_function);

std::vector<T> results;
for (size_t i = 0; i < point_cloud.size(); i++) {
Expand All @@ -130,7 +139,25 @@ std::vector<RangefinderPoint> VoxelFilter(
}

PointCloud VoxelFilter(const PointCloud& point_cloud, const float resolution) {
return PointCloud(VoxelFilter(point_cloud.points(), resolution));
const std::vector<bool> points_used = RandomizedVoxelFilterIndices(
point_cloud.points(), resolution,
[](const RangefinderPoint& point) { return point.position; });

std::vector<RangefinderPoint> filtered_points;
for (size_t i = 0; i < point_cloud.size(); i++) {
if (points_used[i]) {
filtered_points.push_back(point_cloud[i]);
}
}
std::vector<float> filtered_intensities;
CHECK_LE(point_cloud.intensities().size(), point_cloud.points().size());
for (size_t i = 0; i < point_cloud.intensities().size(); i++) {
if (points_used[i]) {
filtered_intensities.push_back(point_cloud.intensities()[i]);
}
}
return PointCloud(std::move(filtered_points),
std::move(filtered_intensities));
}

TimedPointCloud VoxelFilter(const TimedPointCloud& timed_point_cloud,
Expand Down
23 changes: 23 additions & 0 deletions cartographer/sensor/internal/voxel_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace sensor {
namespace {

using ::testing::Contains;
using ::testing::IsEmpty;

TEST(VoxelFilterTest, ReturnsOnePointInEachVoxel) {
const PointCloud point_cloud({{{0.f, 0.f, 0.f}},
Expand All @@ -33,18 +34,40 @@ TEST(VoxelFilterTest, ReturnsOnePointInEachVoxel) {
{{0.f, 0.f, 0.1f}}});
const PointCloud result = VoxelFilter(point_cloud, 0.3f);
ASSERT_EQ(result.size(), 2);
EXPECT_THAT(result.intensities(), IsEmpty());
EXPECT_THAT(point_cloud.points(), Contains(result[0]));
EXPECT_THAT(point_cloud.points(), Contains(result[1]));
EXPECT_THAT(result.points(), Contains(point_cloud[2]));
}

TEST(VoxelFilterTest, CorrectIntensities) {
std::vector<RangefinderPoint> points;
std::vector<float> intensities;
for (int i = 0; i < 100; ++i) {
const float value = 0.1f * i;
// We add points with intensity equal to the z coordinate, so we can later
// verify that the resulting intensities are corresponding to the filtered
// points.
points.push_back({{-100.f, 0.3f, value}});
intensities.push_back(value);
}
const PointCloud point_cloud(points, intensities);
const PointCloud result = VoxelFilter(point_cloud, 0.3f);

ASSERT_EQ(result.intensities().size(), result.points().size());
for (size_t i = 0; i < result.size(); ++i) {
ASSERT_NEAR(result[i].position.z(), result.intensities()[i], 1e-6);
}
}

TEST(VoxelFilterTest, HandlesLargeCoordinates) {
const PointCloud point_cloud({{{100000.f, 0.f, 0.f}},
{{100000.001f, -0.0001f, 0.0001f}},
{{100000.003f, -0.0001f, 0.f}},
{{-200000.f, 0.f, 0.f}}});
const PointCloud result = VoxelFilter(point_cloud, 0.01f);
EXPECT_EQ(result.size(), 2);
EXPECT_THAT(result.intensities(), IsEmpty());
EXPECT_THAT(result.points(), Contains(point_cloud[3]));
}

Expand Down

0 comments on commit d3473fc

Please sign in to comment.