diff --git a/cartographer/mapping_2d/global_trajectory_builder.cc b/cartographer/mapping_2d/global_trajectory_builder.cc index c06a25713c..e9aa38af37 100644 --- a/cartographer/mapping_2d/global_trajectory_builder.cc +++ b/cartographer/mapping_2d/global_trajectory_builder.cc @@ -37,7 +37,7 @@ void GlobalTrajectoryBuilder::AddRangefinderData( const sensor::PointCloud& ranges) { std::unique_ptr insertion_result = local_trajectory_builder_.AddHorizontalRangeData( - time, sensor::RangeData{origin, ranges, {}, {}}); + time, sensor::RangeData{origin, ranges, {}}); if (insertion_result != nullptr) { sparse_pose_graph_->AddScan( insertion_result->time, insertion_result->tracking_to_tracking_2d, diff --git a/cartographer/mapping_2d/local_trajectory_builder.cc b/cartographer/mapping_2d/local_trajectory_builder.cc index 4f6413012c..b72710d4dc 100644 --- a/cartographer/mapping_2d/local_trajectory_builder.cc +++ b/cartographer/mapping_2d/local_trajectory_builder.cc @@ -83,7 +83,7 @@ sensor::RangeData LocalTrajectoryBuilder::TransformAndFilterRangeData( const sensor::RangeData& range_data) const { // Drop any returns below the minimum range and convert returns beyond the // maximum range into misses. - sensor::RangeData returns_and_misses{range_data.origin, {}, {}, {}}; + sensor::RangeData returns_and_misses{range_data.origin, {}, {}}; for (const Eigen::Vector3f& hit : range_data.returns) { const float range = (hit - range_data.origin).norm(); if (range >= options_.laser_min_range()) { diff --git a/cartographer/mapping_2d/map_limits_test.cc b/cartographer/mapping_2d/map_limits_test.cc index c952866177..cb529a27f4 100644 --- a/cartographer/mapping_2d/map_limits_test.cc +++ b/cartographer/mapping_2d/map_limits_test.cc @@ -69,7 +69,7 @@ TEST(MapLimitsTest, ComputeMapLimits) { Eigen::Vector3f::Zero(), {Eigen::Vector3f(-30.f, 1.f, 0.f), Eigen::Vector3f(50.f, -10.f, 0.f)}, {}}, - Compress(sensor::RangeData{Eigen::Vector3f::Zero(), {}, {}, {}}), nullptr, + Compress(sensor::RangeData{Eigen::Vector3f::Zero(), {}, {}}), nullptr, transform::Rigid3d::Identity()}; const mapping::TrajectoryNode trajectory_node{&constant_data, transform::Rigid3d::Identity()}; diff --git a/cartographer/mapping_2d/sparse_pose_graph.cc b/cartographer/mapping_2d/sparse_pose_graph.cc index 0c538fe9ad..fddcfb500a 100644 --- a/cartographer/mapping_2d/sparse_pose_graph.cc +++ b/cartographer/mapping_2d/sparse_pose_graph.cc @@ -99,7 +99,7 @@ void SparsePoseGraph::AddScan( constant_node_data_->push_back(mapping::TrajectoryNode::ConstantData{ time, range_data_in_pose, - Compress(sensor::RangeData{Eigen::Vector3f::Zero(), {}, {}, {}}), submaps, + Compress(sensor::RangeData{Eigen::Vector3f::Zero(), {}, {}}), submaps, tracking_to_pose}); trajectory_nodes_.push_back(mapping::TrajectoryNode{ &constant_node_data_->back(), optimized_pose, @@ -294,25 +294,30 @@ void SparsePoseGraph::WaitForAllComputations() { common::MutexLocker locker(&mutex_); const int num_finished_scans_at_start = constraint_builder_.GetNumFinishedScans(); - while (!locker.AwaitWithTimeout([this]() REQUIRES(mutex_) { - return static_cast(constraint_builder_.GetNumFinishedScans()) == - trajectory_nodes_.size(); - }, common::FromSeconds(1.))) { + while (!locker.AwaitWithTimeout( + [this]() REQUIRES(mutex_) { + return static_cast(constraint_builder_.GetNumFinishedScans()) == + trajectory_nodes_.size(); + }, + common::FromSeconds(1.))) { std::ostringstream progress_info; progress_info << "Optimizing: " << std::fixed << std::setprecision(1) - << 100. * (constraint_builder_.GetNumFinishedScans() - - num_finished_scans_at_start) / + << 100. * + (constraint_builder_.GetNumFinishedScans() - + num_finished_scans_at_start) / (trajectory_nodes_.size() - - num_finished_scans_at_start) << "%..."; + num_finished_scans_at_start) + << "%..."; std::cout << "\r\x1b[K" << progress_info.str() << std::flush; } std::cout << "\r\x1b[KOptimizing: Done. " << std::endl; - constraint_builder_.WhenDone([this, ¬ification]( - const sparse_pose_graph::ConstraintBuilder::Result& result) { - constraints_.insert(constraints_.end(), result.begin(), result.end()); - common::MutexLocker locker(&mutex_); - notification = true; - }); + constraint_builder_.WhenDone( + [this, ¬ification]( + const sparse_pose_graph::ConstraintBuilder::Result& result) { + constraints_.insert(constraints_.end(), result.begin(), result.end()); + common::MutexLocker locker(&mutex_); + notification = true; + }); locker.Await([¬ification]() { return notification; }); } @@ -346,13 +351,13 @@ void SparsePoseGraph::RunOptimization() { const mapping::Submaps* trajectory = trajectory_nodes_[i].constant_data->trajectory; if (extrapolation_transforms.count(trajectory) == 0) { - extrapolation_transforms[trajectory] = - transform::Rigid3d(ExtrapolateSubmapTransforms(submap_transforms_, - *trajectory).back() * - ExtrapolateSubmapTransforms( - optimized_submap_transforms_, *trajectory) - .back() - .inverse()); + extrapolation_transforms[trajectory] = transform::Rigid3d( + ExtrapolateSubmapTransforms(submap_transforms_, *trajectory) + .back() * + ExtrapolateSubmapTransforms(optimized_submap_transforms_, + *trajectory) + .back() + .inverse()); } trajectory_nodes_[i].pose = extrapolation_transforms[trajectory] * trajectory_nodes_[i].pose; diff --git a/cartographer/mapping_3d/kalman_local_trajectory_builder.cc b/cartographer/mapping_3d/kalman_local_trajectory_builder.cc index 8ce9ff7930..ff4b67811f 100644 --- a/cartographer/mapping_3d/kalman_local_trajectory_builder.cc +++ b/cartographer/mapping_3d/kalman_local_trajectory_builder.cc @@ -91,7 +91,7 @@ KalmanLocalTrajectoryBuilder::AddRangefinderData( const transform::Rigid3f tracking_delta = first_pose_prediction_.inverse() * pose_prediction.cast(); const sensor::RangeData range_data_in_first_tracking = - sensor::TransformRangeData(sensor::RangeData{origin, ranges, {}, {}}, + sensor::TransformRangeData(sensor::RangeData{origin, ranges, {}}, tracking_delta); for (const Eigen::Vector3f& hit : range_data_in_first_tracking.returns) { const Eigen::Vector3f delta = hit - range_data_in_first_tracking.origin; diff --git a/cartographer/mapping_3d/submaps.cc b/cartographer/mapping_3d/submaps.cc index 9231000390..7aa764c244 100644 --- a/cartographer/mapping_3d/submaps.cc +++ b/cartographer/mapping_3d/submaps.cc @@ -174,7 +174,7 @@ void InsertSegmentsIntoProbabilityGrid(const std::vector& segments, // information. sensor::RangeData FilterRangeDataByMaxRange(const sensor::RangeData& range_data, const float max_range) { - sensor::RangeData result{range_data.origin, {}, {}, {}}; + sensor::RangeData result{range_data.origin, {}, {}}; for (const Eigen::Vector3f& hit : range_data.returns) { if ((hit - range_data.origin).norm() <= max_range) { result.returns.push_back(hit); diff --git a/cartographer/sensor/compressed_point_cloud.cc b/cartographer/sensor/compressed_point_cloud.cc index 2d67d72235..b2b90e928e 100644 --- a/cartographer/sensor/compressed_point_cloud.cc +++ b/cartographer/sensor/compressed_point_cloud.cc @@ -35,67 +35,6 @@ constexpr int kBitsPerCoordinate = 10; constexpr int kCoordinateMask = (1 << kBitsPerCoordinate) - 1; constexpr int kMaxBitsPerDirection = 23; -// Compressed point cloud into a vector and optionally returns mapping from -// compressed indices to original indices. -std::vector Compress(const PointCloud& point_cloud, - std::vector* new_to_old = nullptr) { - // Distribute points into blocks. - struct RasterPoint { - Eigen::Array3i point; - int index; - }; - using Blocks = mapping_3d::HybridGridBase>; - Blocks blocks(kPrecision, Eigen::Vector3f::Zero()); - int num_blocks = 0; - CHECK_LE(point_cloud.size(), std::numeric_limits::max()); - for (int point_index = 0; point_index < static_cast(point_cloud.size()); - ++point_index) { - const Eigen::Vector3f& point = point_cloud[point_index]; - CHECK_LT(point.cwiseAbs().maxCoeff() / kPrecision, - 1 << kMaxBitsPerDirection) - << "Point out of bounds: " << point; - Eigen::Array3i raster_point; - Eigen::Array3i block_coordinate; - for (int i = 0; i < 3; ++i) { - raster_point[i] = common::RoundToInt(point[i] / kPrecision); - block_coordinate[i] = raster_point[i] >> kBitsPerCoordinate; - raster_point[i] &= kCoordinateMask; - } - auto* const block = blocks.mutable_value(block_coordinate); - num_blocks += block->empty(); - block->push_back({raster_point, point_index}); - } - - if (new_to_old != nullptr) { - new_to_old->clear(); - new_to_old->reserve(point_cloud.size()); - } - - // Encode blocks. - std::vector result; - result.reserve(4 * num_blocks + point_cloud.size()); - for (Blocks::Iterator it(blocks); !it.Done(); it.Next(), --num_blocks) { - const auto& raster_points = it.GetValue(); - CHECK_LE(raster_points.size(), std::numeric_limits::max()); - result.push_back(raster_points.size()); - const Eigen::Array3i block_coordinate = it.GetCellIndex(); - result.push_back(block_coordinate.x()); - result.push_back(block_coordinate.y()); - result.push_back(block_coordinate.z()); - for (const RasterPoint& raster_point : raster_points) { - result.push_back((((raster_point.point.z() << kBitsPerCoordinate) + - raster_point.point.y()) - << kBitsPerCoordinate) + - raster_point.point.x()); - if (new_to_old != nullptr) { - new_to_old->push_back(raster_point.index); - } - } - } - CHECK_EQ(num_blocks, 0); - return result; -} - } // namespace CompressedPointCloud::ConstIterator::ConstIterator( @@ -158,18 +97,58 @@ void CompressedPointCloud::ConstIterator::ReadNextPoint() { } CompressedPointCloud::CompressedPointCloud(const PointCloud& point_cloud) - : point_data_(Compress(point_cloud)), num_points_(point_cloud.size()) {} + : num_points_(point_cloud.size()) { + // Distribute points into blocks. + struct RasterPoint { + Eigen::Array3i point; + int index; + }; + using Blocks = mapping_3d::HybridGridBase>; + Blocks blocks(kPrecision, Eigen::Vector3f::Zero()); + int num_blocks = 0; + CHECK_LE(point_cloud.size(), std::numeric_limits::max()); + for (int point_index = 0; point_index < static_cast(point_cloud.size()); + ++point_index) { + const Eigen::Vector3f& point = point_cloud[point_index]; + CHECK_LT(point.cwiseAbs().maxCoeff() / kPrecision, + 1 << kMaxBitsPerDirection) + << "Point out of bounds: " << point; + Eigen::Array3i raster_point; + Eigen::Array3i block_coordinate; + for (int i = 0; i < 3; ++i) { + raster_point[i] = common::RoundToInt(point[i] / kPrecision); + block_coordinate[i] = raster_point[i] >> kBitsPerCoordinate; + raster_point[i] &= kCoordinateMask; + } + auto* const block = blocks.mutable_value(block_coordinate); + num_blocks += block->empty(); + block->push_back({raster_point, point_index}); + } + + // Encode blocks. + point_data_.reserve(4 * num_blocks + point_cloud.size()); + for (Blocks::Iterator it(blocks); !it.Done(); it.Next(), --num_blocks) { + const auto& raster_points = it.GetValue(); + CHECK_LE(raster_points.size(), std::numeric_limits::max()); + point_data_.push_back(raster_points.size()); + const Eigen::Array3i block_coordinate = it.GetCellIndex(); + point_data_.push_back(block_coordinate.x()); + point_data_.push_back(block_coordinate.y()); + point_data_.push_back(block_coordinate.z()); + for (const RasterPoint& raster_point : raster_points) { + point_data_.push_back((((raster_point.point.z() << kBitsPerCoordinate) + + raster_point.point.y()) + << kBitsPerCoordinate) + + raster_point.point.x()); + } + } + CHECK_EQ(num_blocks, 0); +} CompressedPointCloud::CompressedPointCloud(const std::vector& point_data, size_t num_points) : point_data_(point_data), num_points_(num_points) {} -CompressedPointCloud CompressedPointCloud::CompressAndReturnOrder( - const PointCloud& point_cloud, std::vector* new_to_old) { - return CompressedPointCloud(Compress(point_cloud, new_to_old), - point_cloud.size()); -} - bool CompressedPointCloud::empty() const { return num_points_ == 0; } size_t CompressedPointCloud::size() const { return num_points_; } diff --git a/cartographer/sensor/compressed_point_cloud.h b/cartographer/sensor/compressed_point_cloud.h index eb04b2395b..8729ffaeca 100644 --- a/cartographer/sensor/compressed_point_cloud.h +++ b/cartographer/sensor/compressed_point_cloud.h @@ -40,12 +40,6 @@ class CompressedPointCloud { CompressedPointCloud() : num_points_(0) {} explicit CompressedPointCloud(const PointCloud& point_cloud); - // Returns a compressed point cloud and further returns a mapping 'new_to_old' - // from the compressed indices to the original indices, i.e., conceptually - // compressed[i] = point_cloud[new_to_old[i]]. - static CompressedPointCloud CompressAndReturnOrder( - const PointCloud& point_cloud, std::vector* new_to_old); - // Returns decompressed point cloud. PointCloud Decompress() const; @@ -59,8 +53,8 @@ class CompressedPointCloud { private: CompressedPointCloud(const std::vector& point_data, size_t num_points); - const std::vector point_data_; - const size_t num_points_; + std::vector point_data_; + size_t num_points_; }; // Forward iterator for compressed point clouds. diff --git a/cartographer/sensor/compressed_point_cloud_test.cc b/cartographer/sensor/compressed_point_cloud_test.cc index 301be2d399..d4754280b3 100644 --- a/cartographer/sensor/compressed_point_cloud_test.cc +++ b/cartographer/sensor/compressed_point_cloud_test.cc @@ -116,21 +116,6 @@ TEST(CompressPointCloudTest, CompressesNoGaps) { } } -TEST(CompressPointCloudTest, CompressesAndReturnsOrder) { - PointCloud point_cloud = { - Eigen::Vector3f(1.f, 0.f, 0.f), Eigen::Vector3f(-10.f, 0.f, 0.f), - Eigen::Vector3f(1.f, 0.f, 0.f), Eigen::Vector3f(-10.f, 0.f, 0.f)}; - std::vector new_to_old; - CompressedPointCloud compressed = - CompressedPointCloud::CompressAndReturnOrder(point_cloud, &new_to_old); - EXPECT_EQ(point_cloud.size(), new_to_old.size()); - int i = 0; - for (const Eigen::Vector3f& point : compressed) { - EXPECT_THAT(point, ApproximatelyEquals(point_cloud[new_to_old[i]])); - ++i; - } -} - } // namespace } // namespace sensor } // namespace cartographer diff --git a/cartographer/sensor/proto/sensor.proto b/cartographer/sensor/proto/sensor.proto index 7b5c04cd97..aba52a469f 100644 --- a/cartographer/sensor/proto/sensor.proto +++ b/cartographer/sensor/proto/sensor.proto @@ -74,7 +74,4 @@ message RangeData { optional transform.proto.Vector3f origin = 1; optional PointCloud point_cloud = 2; optional PointCloud missing_echo_point_cloud = 3; - - // Reflectivity values of point_cloud or empty. - repeated int32 reflectivity = 4 [packed = true]; } diff --git a/cartographer/sensor/range_data.cc b/cartographer/sensor/range_data.cc index 14c1955c90..8b05c05882 100644 --- a/cartographer/sensor/range_data.cc +++ b/cartographer/sensor/range_data.cc @@ -22,21 +22,6 @@ namespace cartographer { namespace sensor { -namespace { - -// Reorders reflectivities according to index mapping. -std::vector ReorderReflectivities( - const std::vector& reflectivities, - const std::vector& new_to_old) { - std::vector reordered(reflectivities.size()); - for (size_t i = 0; i < reordered.size(); ++i) { - reordered[i] = reflectivities[new_to_old[i]]; - } - return reordered; -} - -} // namespace - PointCloud ToPointCloud(const proto::LaserScan& proto) { return ToPointCloudWithIntensities(proto).points; } @@ -77,8 +62,6 @@ proto::RangeData ToProto(const RangeData& range_data) { *proto.mutable_origin() = transform::ToProto(range_data.origin); *proto.mutable_point_cloud() = ToProto(range_data.returns); *proto.mutable_missing_echo_point_cloud() = ToProto(range_data.misses); - std::copy(range_data.reflectivities.begin(), range_data.reflectivities.end(), - RepeatedFieldBackInserter(proto.mutable_reflectivity())); return proto; } @@ -87,8 +70,6 @@ RangeData FromProto(const proto::RangeData& proto) { transform::ToEigen(proto.origin()), ToPointCloud(proto.point_cloud()), ToPointCloud(proto.missing_echo_point_cloud()), }; - std::copy(proto.reflectivity().begin(), proto.reflectivity().end(), - std::back_inserter(range_data.reflectivities)); return range_data; } @@ -98,7 +79,6 @@ RangeData TransformRangeData(const RangeData& range_data, transform * range_data.origin, TransformPointCloud(range_data.returns, transform), TransformPointCloud(range_data.misses, transform), - range_data.reflectivities, }; } @@ -109,21 +89,16 @@ RangeData CropRangeData(const RangeData& range_data, const float min_z, } CompressedRangeData Compress(const RangeData& range_data) { - std::vector new_to_old; - CompressedPointCloud compressed_returns = - CompressedPointCloud::CompressAndReturnOrder(range_data.returns, - &new_to_old); return CompressedRangeData{ - range_data.origin, std::move(compressed_returns), + range_data.origin, CompressedPointCloud(range_data.returns), CompressedPointCloud(range_data.misses), - ReorderReflectivities(range_data.reflectivities, new_to_old)}; + }; } RangeData Decompress(const CompressedRangeData& compressed_range_data) { return RangeData{compressed_range_data.origin, compressed_range_data.returns.Decompress(), - compressed_range_data.misses.Decompress(), - compressed_range_data.reflectivities}; + compressed_range_data.misses.Decompress()}; } } // namespace sensor diff --git a/cartographer/sensor/range_data.h b/cartographer/sensor/range_data.h index 9960f2558f..2cb01a23c7 100644 --- a/cartographer/sensor/range_data.h +++ b/cartographer/sensor/range_data.h @@ -33,9 +33,6 @@ struct RangeData { Eigen::Vector3f origin; PointCloud returns; PointCloud misses; - - // Reflectivity value of returns. - std::vector reflectivities; }; // Builds a PointCloud of returns from 'proto', dropping any beams with ranges @@ -67,9 +64,6 @@ struct CompressedRangeData { Eigen::Vector3f origin; CompressedPointCloud returns; CompressedPointCloud misses; - - // Reflectivity value of returns. - std::vector reflectivities; }; CompressedRangeData Compress(const RangeData& range_data); diff --git a/cartographer/sensor/range_data_test.cc b/cartographer/sensor/range_data_test.cc index f439f1c09f..72dca81746 100644 --- a/cartographer/sensor/range_data_test.cc +++ b/cartographer/sensor/range_data_test.cc @@ -74,43 +74,30 @@ TEST(LaserTest, ToPointCloudWithInfinityAndNaN) { EXPECT_TRUE(point_cloud[1].isApprox(Eigen::Vector3f(-3.f, 0.f, 0.f), 1e-6)); } -// Custom matcher for pair entries. -MATCHER_P(PairApproximatelyEquals, expected, +// Custom matcher for Eigen::Vector3f entries. +MATCHER_P(ApproximatelyEquals, expected, string("is equal to ") + PrintToString(expected)) { - return (arg.first - expected.first).isZero(0.001f) && - arg.second == expected.second; + return (arg - expected).isZero(0.001f); } TEST(RangeDataTest, Compression) { + const std::vector returns = {Eigen::Vector3f(0, 1, 2), + Eigen::Vector3f(4, 5, 6), + Eigen::Vector3f(0, 1, 2)}; const RangeData range_data = { - Eigen::Vector3f(1, 1, 1), - {Eigen::Vector3f(0, 1, 2), Eigen::Vector3f(4, 5, 6), - Eigen::Vector3f(0, 1, 2)}, - {Eigen::Vector3f(7, 8, 9)}, - {1, 2, 3}}; + Eigen::Vector3f(1, 1, 1), returns, {Eigen::Vector3f(7, 8, 9)}}; const RangeData actual = Decompress(Compress(range_data)); EXPECT_TRUE(actual.origin.isApprox(Eigen::Vector3f(1, 1, 1), 1e-6)); EXPECT_EQ(3, actual.returns.size()); EXPECT_EQ(1, actual.misses.size()); - EXPECT_EQ(actual.returns.size(), actual.reflectivities.size()); EXPECT_TRUE(actual.misses[0].isApprox(Eigen::Vector3f(7, 8, 9), 0.001f)); - // Returns and their corresponding reflectivities will be reordered, so we - // pair them up into a vector, and compare in an unordered manner. - std::vector> pairs; - for (size_t i = 0; i < actual.returns.size(); ++i) { - pairs.emplace_back(actual.returns[i], actual.reflectivities[i]); - } - EXPECT_EQ(3, pairs.size()); - EXPECT_THAT(pairs, - Contains(PairApproximatelyEquals(std::pair( - Eigen::Vector3f(0, 1, 2), 1)))); - EXPECT_THAT(pairs, - Contains(PairApproximatelyEquals(std::pair( - Eigen::Vector3f(0, 1, 2), 3)))); - EXPECT_THAT(pairs, - Contains(PairApproximatelyEquals(std::pair( - Eigen::Vector3f(4, 5, 6), 2)))); + // Returns will be reordered, so we compare in an unordered manner. + EXPECT_EQ(3, actual.returns.size()); + EXPECT_THAT(actual.returns, + Contains(ApproximatelyEquals(Eigen::Vector3f(0, 1, 2)))); + EXPECT_THAT(actual.returns, + Contains(ApproximatelyEquals(Eigen::Vector3f(4, 5, 6)))); } } // namespace