Converted Submap from struct to class. (#333)
parent
2d75f4ef56
commit
cff0c73857
|
@ -125,7 +125,7 @@ string MapBuilder::SubmapToProto(const int trajectory_id,
|
||||||
|
|
||||||
const Submap* const submap =
|
const Submap* const submap =
|
||||||
trajectory_builders_.at(trajectory_id)->submaps()->Get(submap_index);
|
trajectory_builders_.at(trajectory_id)->submaps()->Get(submap_index);
|
||||||
response->set_submap_version(submap->num_range_data);
|
response->set_submap_version(submap->num_range_data());
|
||||||
submap->ToResponseProto(submap_transforms[submap_index], response);
|
submap->ToResponseProto(submap_transforms[submap_index], response);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,26 +56,36 @@ inline uint8 ProbabilityToLogOddsInteger(const float probability) {
|
||||||
// track of how many range data were inserted into it, and sets the
|
// track of how many range data were inserted into it, and sets the
|
||||||
// 'finished_probability_grid' to be used for loop closing once the map no
|
// 'finished_probability_grid' to be used for loop closing once the map no
|
||||||
// longer changes.
|
// longer changes.
|
||||||
// TODO(hrapp): This should be a class now.
|
class Submap {
|
||||||
struct Submap {
|
public:
|
||||||
Submap(const transform::Rigid3d& local_pose) : local_pose(local_pose) {}
|
Submap(const transform::Rigid3d& local_pose) : local_pose_(local_pose) {}
|
||||||
virtual ~Submap() {}
|
virtual ~Submap() {}
|
||||||
|
|
||||||
// Local SLAM pose of this submap.
|
// Local SLAM pose of this submap.
|
||||||
const transform::Rigid3d local_pose;
|
transform::Rigid3d local_pose() const { return local_pose_; }
|
||||||
|
|
||||||
// Number of RangeData inserted.
|
// Number of RangeData inserted.
|
||||||
int num_range_data = 0;
|
size_t num_range_data() const { return num_range_data_; }
|
||||||
|
|
||||||
// The 'finished_probability_grid' when this submap is finished and will not
|
// The 'finished_probability_grid' when this submap is finished and will not
|
||||||
// change anymore. Otherwise, this is nullptr and the next call to
|
// change anymore. Otherwise, this is nullptr and the next call to
|
||||||
// InsertRangeData() will change the submap.
|
// InsertRangeData() will change the submap.
|
||||||
const mapping_2d::ProbabilityGrid* finished_probability_grid = nullptr;
|
const mapping_2d::ProbabilityGrid* finished_probability_grid() const {
|
||||||
|
return finished_probability_grid_;
|
||||||
|
}
|
||||||
|
|
||||||
// Fills data into the 'response'.
|
// Fills data into the 'response'.
|
||||||
virtual void ToResponseProto(
|
virtual void ToResponseProto(
|
||||||
const transform::Rigid3d& global_submap_pose,
|
const transform::Rigid3d& global_submap_pose,
|
||||||
proto::SubmapQuery::Response* response) const = 0;
|
proto::SubmapQuery::Response* response) const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const transform::Rigid3d local_pose_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// TODO(hrapp): All of this should be private.
|
||||||
|
int num_range_data_ = 0;
|
||||||
|
const mapping_2d::ProbabilityGrid* finished_probability_grid_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Submaps is a sequence of maps to which scans are matched and into which scans
|
// Submaps is a sequence of maps to which scans are matched and into which scans
|
||||||
|
|
|
@ -71,7 +71,7 @@ void LocalTrajectoryBuilder::ScanMatch(
|
||||||
const sensor::RangeData& range_data_in_tracking_2d,
|
const sensor::RangeData& range_data_in_tracking_2d,
|
||||||
transform::Rigid3d* pose_observation) {
|
transform::Rigid3d* pose_observation) {
|
||||||
const ProbabilityGrid& probability_grid =
|
const ProbabilityGrid& probability_grid =
|
||||||
submaps_.Get(submaps_.matching_index())->probability_grid;
|
submaps_.Get(submaps_.matching_index())->probability_grid();
|
||||||
transform::Rigid2d pose_prediction_2d =
|
transform::Rigid2d pose_prediction_2d =
|
||||||
transform::Project2D(pose_prediction * tracking_to_tracking_2d.inverse());
|
transform::Project2D(pose_prediction * tracking_to_tracking_2d.inverse());
|
||||||
// The online correlative scan matcher will refine the initial estimate for
|
// The online correlative scan matcher will refine the initial estimate for
|
||||||
|
|
|
@ -116,7 +116,7 @@ void SparsePoseGraph::AddScan(
|
||||||
submap_data_.at(submap_id).submap = insertion_submaps.back();
|
submap_data_.at(submap_id).submap = insertion_submaps.back();
|
||||||
}
|
}
|
||||||
const mapping::Submap* const finished_submap =
|
const mapping::Submap* const finished_submap =
|
||||||
insertion_submaps.front()->finished_probability_grid != nullptr
|
insertion_submaps.front()->finished_probability_grid() != nullptr
|
||||||
? insertion_submaps.front()
|
? insertion_submaps.front()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
|
@ -430,7 +430,8 @@ transform::Rigid3d SparsePoseGraph::GetLocalToGlobalTransform(
|
||||||
.at(mapping::SubmapId{
|
.at(mapping::SubmapId{
|
||||||
trajectory_id,
|
trajectory_id,
|
||||||
static_cast<int>(extrapolated_submap_transforms.size()) - 1})
|
static_cast<int>(extrapolated_submap_transforms.size()) - 1})
|
||||||
.submap->local_pose.inverse();
|
.submap->local_pose()
|
||||||
|
.inverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<int>> SparsePoseGraph::GetConnectedTrajectories() {
|
std::vector<std::vector<int>> SparsePoseGraph::GetConnectedTrajectories() {
|
||||||
|
@ -474,8 +475,8 @@ std::vector<transform::Rigid3d> SparsePoseGraph::ExtrapolateSubmapTransforms(
|
||||||
trajectory_id, static_cast<int>(result.size()) - 1};
|
trajectory_id, static_cast<int>(result.size()) - 1};
|
||||||
result.push_back(
|
result.push_back(
|
||||||
result.back() *
|
result.back() *
|
||||||
submap_data_.at(previous_submap_id).submap->local_pose.inverse() *
|
submap_data_.at(previous_submap_id).submap->local_pose().inverse() *
|
||||||
submap_data.submap->local_pose);
|
submap_data.submap->local_pose());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace mapping_2d {
|
||||||
namespace sparse_pose_graph {
|
namespace sparse_pose_graph {
|
||||||
|
|
||||||
transform::Rigid2d ComputeSubmapPose(const mapping::Submap& submap) {
|
transform::Rigid2d ComputeSubmapPose(const mapping::Submap& submap) {
|
||||||
return transform::Project2D(submap.local_pose);
|
return transform::Project2D(submap.local_pose());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstraintBuilder::ConstraintBuilder(
|
ConstraintBuilder::ConstraintBuilder(
|
||||||
|
@ -74,7 +74,7 @@ void ConstraintBuilder::MaybeAddConstraint(
|
||||||
++pending_computations_[current_computation_];
|
++pending_computations_[current_computation_];
|
||||||
const int current_computation = current_computation_;
|
const int current_computation = current_computation_;
|
||||||
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
||||||
submap_id, submap->finished_probability_grid, [=]() EXCLUDES(mutex_) {
|
submap_id, submap->finished_probability_grid(), [=]() EXCLUDES(mutex_) {
|
||||||
ComputeConstraint(submap_id, submap, node_id,
|
ComputeConstraint(submap_id, submap, node_id,
|
||||||
false, /* match_full_submap */
|
false, /* match_full_submap */
|
||||||
nullptr, /* trajectory_connectivity */
|
nullptr, /* trajectory_connectivity */
|
||||||
|
@ -94,7 +94,7 @@ void ConstraintBuilder::MaybeAddGlobalConstraint(
|
||||||
++pending_computations_[current_computation_];
|
++pending_computations_[current_computation_];
|
||||||
const int current_computation = current_computation_;
|
const int current_computation = current_computation_;
|
||||||
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
||||||
submap_id, submap->finished_probability_grid, [=]() EXCLUDES(mutex_) {
|
submap_id, submap->finished_probability_grid(), [=]() EXCLUDES(mutex_) {
|
||||||
ComputeConstraint(submap_id, submap, node_id,
|
ComputeConstraint(submap_id, submap, node_id,
|
||||||
true, /* match_full_submap */
|
true, /* match_full_submap */
|
||||||
trajectory_connectivity, point_cloud,
|
trajectory_connectivity, point_cloud,
|
||||||
|
|
|
@ -103,18 +103,18 @@ proto::SubmapsOptions CreateSubmapsOptions(
|
||||||
Submap::Submap(const MapLimits& limits, const Eigen::Vector2f& origin)
|
Submap::Submap(const MapLimits& limits, const Eigen::Vector2f& origin)
|
||||||
: mapping::Submap(transform::Rigid3d::Translation(
|
: mapping::Submap(transform::Rigid3d::Translation(
|
||||||
Eigen::Vector3d(origin.x(), origin.y(), 0.))),
|
Eigen::Vector3d(origin.x(), origin.y(), 0.))),
|
||||||
probability_grid(limits) {}
|
probability_grid_(limits) {}
|
||||||
|
|
||||||
void Submap::ToResponseProto(
|
void Submap::ToResponseProto(
|
||||||
const transform::Rigid3d&,
|
const transform::Rigid3d&,
|
||||||
mapping::proto::SubmapQuery::Response* const response) const {
|
mapping::proto::SubmapQuery::Response* const response) const {
|
||||||
Eigen::Array2i offset;
|
Eigen::Array2i offset;
|
||||||
CellLimits limits;
|
CellLimits limits;
|
||||||
probability_grid.ComputeCroppedLimits(&offset, &limits);
|
probability_grid_.ComputeCroppedLimits(&offset, &limits);
|
||||||
|
|
||||||
string cells;
|
string cells;
|
||||||
for (const Eigen::Array2i& xy_index : XYIndexRangeIterator(limits)) {
|
for (const Eigen::Array2i& xy_index : XYIndexRangeIterator(limits)) {
|
||||||
if (probability_grid.IsKnown(xy_index + offset)) {
|
if (probability_grid_.IsKnown(xy_index + offset)) {
|
||||||
// We would like to add 'delta' but this is not possible using a value and
|
// We would like to add 'delta' but this is not possible using a value and
|
||||||
// alpha. We use premultiplied alpha, so when 'delta' is positive we can
|
// alpha. We use premultiplied alpha, so when 'delta' is positive we can
|
||||||
// add it by setting 'alpha' to zero. If it is negative, we set 'value' to
|
// add it by setting 'alpha' to zero. If it is negative, we set 'value' to
|
||||||
|
@ -123,7 +123,7 @@ void Submap::ToResponseProto(
|
||||||
// detect visually for the user, though.
|
// detect visually for the user, though.
|
||||||
const int delta =
|
const int delta =
|
||||||
128 - mapping::ProbabilityToLogOddsInteger(
|
128 - mapping::ProbabilityToLogOddsInteger(
|
||||||
probability_grid.GetProbability(xy_index + offset));
|
probability_grid_.GetProbability(xy_index + offset));
|
||||||
const uint8 alpha = delta > 0 ? 0 : -delta;
|
const uint8 alpha = delta > 0 ? 0 : -delta;
|
||||||
const uint8 value = delta > 0 ? delta : 0;
|
const uint8 value = delta > 0 ? delta : 0;
|
||||||
cells.push_back(value);
|
cells.push_back(value);
|
||||||
|
@ -138,14 +138,14 @@ void Submap::ToResponseProto(
|
||||||
|
|
||||||
response->set_width(limits.num_x_cells);
|
response->set_width(limits.num_x_cells);
|
||||||
response->set_height(limits.num_y_cells);
|
response->set_height(limits.num_y_cells);
|
||||||
const double resolution = probability_grid.limits().resolution();
|
const double resolution = probability_grid_.limits().resolution();
|
||||||
response->set_resolution(resolution);
|
response->set_resolution(resolution);
|
||||||
const double max_x =
|
const double max_x =
|
||||||
probability_grid.limits().max().x() - resolution * offset.y();
|
probability_grid_.limits().max().x() - resolution * offset.y();
|
||||||
const double max_y =
|
const double max_y =
|
||||||
probability_grid.limits().max().y() - resolution * offset.x();
|
probability_grid_.limits().max().y() - resolution * offset.x();
|
||||||
*response->mutable_slice_pose() = transform::ToProto(
|
*response->mutable_slice_pose() = transform::ToProto(
|
||||||
local_pose.inverse() *
|
local_pose().inverse() *
|
||||||
transform::Rigid3d::Translation(Eigen::Vector3d(max_x, max_y, 0.)));
|
transform::Rigid3d::Translation(Eigen::Vector3d(max_x, max_y, 0.)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,12 +160,12 @@ Submaps::Submaps(const proto::SubmapsOptions& options)
|
||||||
void Submaps::InsertRangeData(const sensor::RangeData& range_data) {
|
void Submaps::InsertRangeData(const sensor::RangeData& range_data) {
|
||||||
for (const int index : insertion_indices()) {
|
for (const int index : insertion_indices()) {
|
||||||
Submap* submap = submaps_[index].get();
|
Submap* submap = submaps_[index].get();
|
||||||
CHECK(submap->finished_probability_grid == nullptr);
|
CHECK(submap->finished_probability_grid_ == nullptr);
|
||||||
range_data_inserter_.Insert(range_data, &submap->probability_grid);
|
range_data_inserter_.Insert(range_data, &submap->probability_grid_);
|
||||||
++submap->num_range_data;
|
++submap->num_range_data_;
|
||||||
}
|
}
|
||||||
const Submap* const last_submap = Get(size() - 1);
|
const Submap* const last_submap = Get(size() - 1);
|
||||||
if (last_submap->num_range_data == options_.num_range_data()) {
|
if (last_submap->num_range_data_ == options_.num_range_data()) {
|
||||||
AddSubmap(range_data.origin.head<2>());
|
AddSubmap(range_data.origin.head<2>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,14 +182,14 @@ void Submaps::FinishSubmap(int index) {
|
||||||
// Crop the finished Submap before inserting a new Submap to reduce peak
|
// Crop the finished Submap before inserting a new Submap to reduce peak
|
||||||
// memory usage a bit.
|
// memory usage a bit.
|
||||||
Submap* submap = submaps_[index].get();
|
Submap* submap = submaps_[index].get();
|
||||||
CHECK(submap->finished_probability_grid == nullptr);
|
CHECK(submap->finished_probability_grid_ == nullptr);
|
||||||
submap->probability_grid =
|
submap->probability_grid_ =
|
||||||
ComputeCroppedProbabilityGrid(submap->probability_grid);
|
ComputeCroppedProbabilityGrid(submap->probability_grid_);
|
||||||
submap->finished_probability_grid = &submap->probability_grid;
|
submap->finished_probability_grid_ = &submap->probability_grid_;
|
||||||
if (options_.output_debug_images()) {
|
if (options_.output_debug_images()) {
|
||||||
// Output the Submap that won't be changed from now on.
|
// Output the Submap that won't be changed from now on.
|
||||||
WriteDebugImage("submap" + std::to_string(index) + ".webp",
|
WriteDebugImage("submap" + std::to_string(index) + ".webp",
|
||||||
submap->probability_grid);
|
submap->probability_grid_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,14 +41,21 @@ ProbabilityGrid ComputeCroppedProbabilityGrid(
|
||||||
proto::SubmapsOptions CreateSubmapsOptions(
|
proto::SubmapsOptions CreateSubmapsOptions(
|
||||||
common::LuaParameterDictionary* parameter_dictionary);
|
common::LuaParameterDictionary* parameter_dictionary);
|
||||||
|
|
||||||
struct Submap : public mapping::Submap {
|
class Submap : public mapping::Submap {
|
||||||
|
public:
|
||||||
Submap(const MapLimits& limits, const Eigen::Vector2f& origin);
|
Submap(const MapLimits& limits, const Eigen::Vector2f& origin);
|
||||||
|
|
||||||
ProbabilityGrid probability_grid;
|
const ProbabilityGrid& probability_grid() const { return probability_grid_; }
|
||||||
|
|
||||||
void ToResponseProto(
|
void ToResponseProto(
|
||||||
const transform::Rigid3d& global_submap_pose,
|
const transform::Rigid3d& global_submap_pose,
|
||||||
mapping::proto::SubmapQuery::Response* response) const override;
|
mapping::proto::SubmapQuery::Response* response) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// TODO(hrapp): Remove friend declaration.
|
||||||
|
friend class Submaps;
|
||||||
|
|
||||||
|
ProbabilityGrid probability_grid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A container of Submaps.
|
// A container of Submaps.
|
||||||
|
|
|
@ -51,12 +51,12 @@ TEST(SubmapsTest, TheRightNumberOfScansAreInserted) {
|
||||||
const int matching = submaps.matching_index();
|
const int matching = submaps.matching_index();
|
||||||
// Except for the first, maps should only be returned after enough scans.
|
// Except for the first, maps should only be returned after enough scans.
|
||||||
if (matching != 0) {
|
if (matching != 0) {
|
||||||
EXPECT_LE(kNumRangeData, submaps.Get(matching)->num_range_data);
|
EXPECT_LE(kNumRangeData, submaps.Get(matching)->num_range_data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i != submaps.size() - 2; ++i) {
|
for (int i = 0; i != submaps.size() - 2; ++i) {
|
||||||
// Submaps should not be left without the right number of scans in them.
|
// Submaps should not be left without the right number of scans in them.
|
||||||
EXPECT_EQ(kNumRangeData * 2, submaps.Get(i)->num_range_data);
|
EXPECT_EQ(kNumRangeData * 2, submaps.Get(i)->num_range_data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ KalmanLocalTrajectoryBuilder::AddAccumulatedRangeData(
|
||||||
const Submap* const matching_submap =
|
const Submap* const matching_submap =
|
||||||
submaps_->Get(submaps_->matching_index());
|
submaps_->Get(submaps_->matching_index());
|
||||||
transform::Rigid3d initial_ceres_pose =
|
transform::Rigid3d initial_ceres_pose =
|
||||||
matching_submap->local_pose.inverse() * pose_prediction;
|
matching_submap->local_pose().inverse() * pose_prediction;
|
||||||
sensor::AdaptiveVoxelFilter adaptive_voxel_filter(
|
sensor::AdaptiveVoxelFilter adaptive_voxel_filter(
|
||||||
options_.high_resolution_adaptive_voxel_filter_options());
|
options_.high_resolution_adaptive_voxel_filter_options());
|
||||||
const sensor::PointCloud filtered_point_cloud_in_tracking =
|
const sensor::PointCloud filtered_point_cloud_in_tracking =
|
||||||
|
@ -154,7 +154,7 @@ KalmanLocalTrajectoryBuilder::AddAccumulatedRangeData(
|
||||||
const transform::Rigid3d initial_pose = initial_ceres_pose;
|
const transform::Rigid3d initial_pose = initial_ceres_pose;
|
||||||
real_time_correlative_scan_matcher_->Match(
|
real_time_correlative_scan_matcher_->Match(
|
||||||
initial_pose, filtered_point_cloud_in_tracking,
|
initial_pose, filtered_point_cloud_in_tracking,
|
||||||
matching_submap->high_resolution_hybrid_grid, &initial_ceres_pose);
|
matching_submap->high_resolution_hybrid_grid(), &initial_ceres_pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
transform::Rigid3d pose_observation_in_submap;
|
transform::Rigid3d pose_observation_in_submap;
|
||||||
|
@ -166,12 +166,12 @@ KalmanLocalTrajectoryBuilder::AddAccumulatedRangeData(
|
||||||
low_resolution_adaptive_voxel_filter.Filter(filtered_range_data.returns);
|
low_resolution_adaptive_voxel_filter.Filter(filtered_range_data.returns);
|
||||||
ceres_scan_matcher_->Match(scan_matcher_pose_estimate_, initial_ceres_pose,
|
ceres_scan_matcher_->Match(scan_matcher_pose_estimate_, initial_ceres_pose,
|
||||||
{{&filtered_point_cloud_in_tracking,
|
{{&filtered_point_cloud_in_tracking,
|
||||||
&matching_submap->high_resolution_hybrid_grid},
|
&matching_submap->high_resolution_hybrid_grid()},
|
||||||
{&low_resolution_point_cloud_in_tracking,
|
{&low_resolution_point_cloud_in_tracking,
|
||||||
&matching_submap->low_resolution_hybrid_grid}},
|
&matching_submap->low_resolution_hybrid_grid()}},
|
||||||
&pose_observation_in_submap, &summary);
|
&pose_observation_in_submap, &summary);
|
||||||
const transform::Rigid3d pose_observation =
|
const transform::Rigid3d pose_observation =
|
||||||
matching_submap->local_pose * pose_observation_in_submap;
|
matching_submap->local_pose() * pose_observation_in_submap;
|
||||||
pose_tracker_->AddPoseObservation(
|
pose_tracker_->AddPoseObservation(
|
||||||
time, pose_observation,
|
time, pose_observation,
|
||||||
options_.kalman_local_trajectory_builder_options()
|
options_.kalman_local_trajectory_builder_options()
|
||||||
|
|
|
@ -241,7 +241,7 @@ OptimizingLocalTrajectoryBuilder::MaybeOptimize(const common::Time time) {
|
||||||
// We transform the states in 'batches_' in place to be in the submap frame as
|
// We transform the states in 'batches_' in place to be in the submap frame as
|
||||||
// expected by the OccupiedSpaceCostFunctor. This is reverted after solving
|
// expected by the OccupiedSpaceCostFunctor. This is reverted after solving
|
||||||
// the optimization problem.
|
// the optimization problem.
|
||||||
TransformStates(matching_submap->local_pose.inverse());
|
TransformStates(matching_submap->local_pose().inverse());
|
||||||
for (size_t i = 0; i < batches_.size(); ++i) {
|
for (size_t i = 0; i < batches_.size(); ++i) {
|
||||||
Batch& batch = batches_[i];
|
Batch& batch = batches_[i];
|
||||||
problem.AddResidualBlock(
|
problem.AddResidualBlock(
|
||||||
|
@ -253,7 +253,7 @@ OptimizingLocalTrajectoryBuilder::MaybeOptimize(const common::Time time) {
|
||||||
std::sqrt(static_cast<double>(
|
std::sqrt(static_cast<double>(
|
||||||
batch.high_resolution_filtered_points.size())),
|
batch.high_resolution_filtered_points.size())),
|
||||||
batch.high_resolution_filtered_points,
|
batch.high_resolution_filtered_points,
|
||||||
matching_submap->high_resolution_hybrid_grid),
|
matching_submap->high_resolution_hybrid_grid()),
|
||||||
batch.high_resolution_filtered_points.size()),
|
batch.high_resolution_filtered_points.size()),
|
||||||
nullptr, batch.state.translation.data(), batch.state.rotation.data());
|
nullptr, batch.state.translation.data(), batch.state.rotation.data());
|
||||||
problem.AddResidualBlock(
|
problem.AddResidualBlock(
|
||||||
|
@ -265,7 +265,7 @@ OptimizingLocalTrajectoryBuilder::MaybeOptimize(const common::Time time) {
|
||||||
std::sqrt(static_cast<double>(
|
std::sqrt(static_cast<double>(
|
||||||
batch.low_resolution_filtered_points.size())),
|
batch.low_resolution_filtered_points.size())),
|
||||||
batch.low_resolution_filtered_points,
|
batch.low_resolution_filtered_points,
|
||||||
matching_submap->low_resolution_hybrid_grid),
|
matching_submap->low_resolution_hybrid_grid()),
|
||||||
batch.low_resolution_filtered_points.size()),
|
batch.low_resolution_filtered_points.size()),
|
||||||
nullptr, batch.state.translation.data(), batch.state.rotation.data());
|
nullptr, batch.state.translation.data(), batch.state.rotation.data());
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ OptimizingLocalTrajectoryBuilder::MaybeOptimize(const common::Time time) {
|
||||||
ceres::Solve(ceres_solver_options_, &problem, &summary);
|
ceres::Solve(ceres_solver_options_, &problem, &summary);
|
||||||
// The optimized states in 'batches_' are in the submap frame and we transform
|
// The optimized states in 'batches_' are in the submap frame and we transform
|
||||||
// them in place to be in the local SLAM frame again.
|
// them in place to be in the local SLAM frame again.
|
||||||
TransformStates(matching_submap->local_pose);
|
TransformStates(matching_submap->local_pose());
|
||||||
if (num_accumulated_ < options_.scans_per_accumulation()) {
|
if (num_accumulated_ < options_.scans_per_accumulation()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,8 +81,8 @@ void SparsePoseGraph::GrowSubmapTransformsAsNeeded(
|
||||||
submap_data.at(trajectory_id).at(first_submap_id.submap_index).pose;
|
submap_data.at(trajectory_id).at(first_submap_id.submap_index).pose;
|
||||||
optimization_problem_.AddSubmap(
|
optimization_problem_.AddSubmap(
|
||||||
trajectory_id, first_submap_pose *
|
trajectory_id, first_submap_pose *
|
||||||
insertion_submaps[0]->local_pose.inverse() *
|
insertion_submaps[0]->local_pose().inverse() *
|
||||||
insertion_submaps[1]->local_pose);
|
insertion_submaps[1]->local_pose());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,8 +113,9 @@ void SparsePoseGraph::AddScan(
|
||||||
submap_ids_.emplace(insertion_submaps.back(), submap_id);
|
submap_ids_.emplace(insertion_submaps.back(), submap_id);
|
||||||
submap_data_.at(submap_id).submap = insertion_submaps.back();
|
submap_data_.at(submap_id).submap = insertion_submaps.back();
|
||||||
}
|
}
|
||||||
const Submap* const finished_submap =
|
const Submap* const finished_submap = insertion_submaps.front()->finished()
|
||||||
insertion_submaps.front()->finished ? insertion_submaps.front() : nullptr;
|
? insertion_submaps.front()
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
// Make sure we have a sampler for this trajectory.
|
// Make sure we have a sampler for this trajectory.
|
||||||
if (!global_localization_samplers_[trajectory_id]) {
|
if (!global_localization_samplers_[trajectory_id]) {
|
||||||
|
@ -235,7 +236,7 @@ void SparsePoseGraph::ComputeConstraintsForScan(
|
||||||
.at(matching_id.trajectory_id)
|
.at(matching_id.trajectory_id)
|
||||||
.at(matching_id.submap_index)
|
.at(matching_id.submap_index)
|
||||||
.pose *
|
.pose *
|
||||||
matching_submap->local_pose.inverse() * pose;
|
matching_submap->local_pose().inverse() * pose;
|
||||||
const mapping::NodeId node_id{
|
const mapping::NodeId node_id{
|
||||||
matching_id.trajectory_id,
|
matching_id.trajectory_id,
|
||||||
static_cast<size_t>(matching_id.trajectory_id) <
|
static_cast<size_t>(matching_id.trajectory_id) <
|
||||||
|
@ -252,7 +253,7 @@ void SparsePoseGraph::ComputeConstraintsForScan(
|
||||||
CHECK(submap_data_.at(submap_id).state == SubmapState::kActive);
|
CHECK(submap_data_.at(submap_id).state == SubmapState::kActive);
|
||||||
submap_data_.at(submap_id).node_ids.emplace(node_id);
|
submap_data_.at(submap_id).node_ids.emplace(node_id);
|
||||||
const transform::Rigid3d constraint_transform =
|
const transform::Rigid3d constraint_transform =
|
||||||
submap->local_pose.inverse() * pose;
|
submap->local_pose().inverse() * pose;
|
||||||
constraints_.push_back(
|
constraints_.push_back(
|
||||||
Constraint{submap_id,
|
Constraint{submap_id,
|
||||||
node_id,
|
node_id,
|
||||||
|
@ -432,7 +433,8 @@ transform::Rigid3d SparsePoseGraph::GetLocalToGlobalTransform(
|
||||||
.at(mapping::SubmapId{
|
.at(mapping::SubmapId{
|
||||||
trajectory_id,
|
trajectory_id,
|
||||||
static_cast<int>(extrapolated_submap_transforms.size()) - 1})
|
static_cast<int>(extrapolated_submap_transforms.size()) - 1})
|
||||||
.submap->local_pose.inverse();
|
.submap->local_pose()
|
||||||
|
.inverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<int>> SparsePoseGraph::GetConnectedTrajectories() {
|
std::vector<std::vector<int>> SparsePoseGraph::GetConnectedTrajectories() {
|
||||||
|
@ -476,8 +478,8 @@ std::vector<transform::Rigid3d> SparsePoseGraph::ExtrapolateSubmapTransforms(
|
||||||
trajectory_id, static_cast<int>(result.size()) - 1};
|
trajectory_id, static_cast<int>(result.size()) - 1};
|
||||||
result.push_back(
|
result.push_back(
|
||||||
result.back() *
|
result.back() *
|
||||||
submap_data_.at(previous_submap_id).submap->local_pose.inverse() *
|
submap_data_.at(previous_submap_id).submap->local_pose().inverse() *
|
||||||
submap_data.submap->local_pose);
|
submap_data.submap->local_pose());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ void ConstraintBuilder::MaybeAddConstraint(
|
||||||
++pending_computations_[current_computation_];
|
++pending_computations_[current_computation_];
|
||||||
const int current_computation = current_computation_;
|
const int current_computation = current_computation_;
|
||||||
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
||||||
submap_id, submap_nodes, &submap->high_resolution_hybrid_grid,
|
submap_id, submap_nodes, &submap->high_resolution_hybrid_grid(),
|
||||||
[=]() EXCLUDES(mutex_) {
|
[=]() EXCLUDES(mutex_) {
|
||||||
ComputeConstraint(submap_id, submap, node_id,
|
ComputeConstraint(submap_id, submap, node_id,
|
||||||
false, /* match_full_submap */
|
false, /* match_full_submap */
|
||||||
|
@ -96,7 +96,7 @@ void ConstraintBuilder::MaybeAddGlobalConstraint(
|
||||||
++pending_computations_[current_computation_];
|
++pending_computations_[current_computation_];
|
||||||
const int current_computation = current_computation_;
|
const int current_computation = current_computation_;
|
||||||
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
ScheduleSubmapScanMatcherConstructionAndQueueWorkItem(
|
||||||
submap_id, submap_nodes, &submap->high_resolution_hybrid_grid,
|
submap_id, submap_nodes, &submap->high_resolution_hybrid_grid(),
|
||||||
[=]() EXCLUDES(mutex_) {
|
[=]() EXCLUDES(mutex_) {
|
||||||
ComputeConstraint(
|
ComputeConstraint(
|
||||||
submap_id, submap, node_id, true, /* match_full_submap */
|
submap_id, submap, node_id, true, /* match_full_submap */
|
||||||
|
|
|
@ -224,9 +224,9 @@ std::vector<Eigen::Array4i> ExtractVoxelData(
|
||||||
const HybridGrid& hybrid_grid, const transform::Rigid3f& transform,
|
const HybridGrid& hybrid_grid, const transform::Rigid3f& transform,
|
||||||
Eigen::Array2i* min_index, Eigen::Array2i* max_index) {
|
Eigen::Array2i* min_index, Eigen::Array2i* max_index) {
|
||||||
std::vector<Eigen::Array4i> voxel_indices_and_probabilities;
|
std::vector<Eigen::Array4i> voxel_indices_and_probabilities;
|
||||||
const float resolution_inverse = 1. / hybrid_grid.resolution();
|
const float resolution_inverse = 1.f / hybrid_grid.resolution();
|
||||||
|
|
||||||
constexpr double kXrayObstructedCellProbabilityLimit = 0.501;
|
constexpr float kXrayObstructedCellProbabilityLimit = 0.501f;
|
||||||
for (auto it = HybridGrid::Iterator(hybrid_grid); !it.Done(); it.Next()) {
|
for (auto it = HybridGrid::Iterator(hybrid_grid); !it.Done(); it.Next()) {
|
||||||
const uint16 probability_value = it.GetValue();
|
const uint16 probability_value = it.GetValue();
|
||||||
const float probability = mapping::ValueToProbability(probability_value);
|
const float probability = mapping::ValueToProbability(probability_value);
|
||||||
|
@ -323,22 +323,22 @@ proto::SubmapsOptions CreateSubmapsOptions(
|
||||||
Submap::Submap(const float high_resolution, const float low_resolution,
|
Submap::Submap(const float high_resolution, const float low_resolution,
|
||||||
const transform::Rigid3d& local_pose)
|
const transform::Rigid3d& local_pose)
|
||||||
: mapping::Submap(local_pose),
|
: mapping::Submap(local_pose),
|
||||||
high_resolution_hybrid_grid(high_resolution),
|
high_resolution_hybrid_grid_(high_resolution),
|
||||||
low_resolution_hybrid_grid(low_resolution) {}
|
low_resolution_hybrid_grid_(low_resolution) {}
|
||||||
|
|
||||||
void Submap::ToResponseProto(
|
void Submap::ToResponseProto(
|
||||||
const transform::Rigid3d& global_submap_pose,
|
const transform::Rigid3d& global_submap_pose,
|
||||||
mapping::proto::SubmapQuery::Response* const response) const {
|
mapping::proto::SubmapQuery::Response* const response) const {
|
||||||
// Generate an X-ray view through the 'hybrid_grid', aligned to the xy-plane
|
// Generate an X-ray view through the 'hybrid_grid', aligned to the xy-plane
|
||||||
// in the global map frame.
|
// in the global map frame.
|
||||||
const float resolution = high_resolution_hybrid_grid.resolution();
|
const float resolution = high_resolution_hybrid_grid_.resolution();
|
||||||
response->set_resolution(resolution);
|
response->set_resolution(resolution);
|
||||||
|
|
||||||
// Compute a bounding box for the texture.
|
// Compute a bounding box for the texture.
|
||||||
Eigen::Array2i min_index(INT_MAX, INT_MAX);
|
Eigen::Array2i min_index(INT_MAX, INT_MAX);
|
||||||
Eigen::Array2i max_index(INT_MIN, INT_MIN);
|
Eigen::Array2i max_index(INT_MIN, INT_MIN);
|
||||||
const std::vector<Eigen::Array4i> voxel_indices_and_probabilities =
|
const std::vector<Eigen::Array4i> voxel_indices_and_probabilities =
|
||||||
ExtractVoxelData(high_resolution_hybrid_grid,
|
ExtractVoxelData(high_resolution_hybrid_grid_,
|
||||||
global_submap_pose.cast<float>(), &min_index,
|
global_submap_pose.cast<float>(), &min_index,
|
||||||
&max_index);
|
&max_index);
|
||||||
|
|
||||||
|
@ -383,17 +383,17 @@ void Submaps::InsertRangeData(const sensor::RangeData& range_data,
|
||||||
for (const int index : insertion_indices()) {
|
for (const int index : insertion_indices()) {
|
||||||
Submap* submap = submaps_[index].get();
|
Submap* submap = submaps_[index].get();
|
||||||
const sensor::RangeData transformed_range_data = sensor::TransformRangeData(
|
const sensor::RangeData transformed_range_data = sensor::TransformRangeData(
|
||||||
range_data, submap->local_pose.inverse().cast<float>());
|
range_data, submap->local_pose().inverse().cast<float>());
|
||||||
range_data_inserter_.Insert(
|
range_data_inserter_.Insert(
|
||||||
FilterRangeDataByMaxRange(transformed_range_data,
|
FilterRangeDataByMaxRange(transformed_range_data,
|
||||||
options_.high_resolution_max_range()),
|
options_.high_resolution_max_range()),
|
||||||
&submap->high_resolution_hybrid_grid);
|
&submap->high_resolution_hybrid_grid_);
|
||||||
range_data_inserter_.Insert(transformed_range_data,
|
range_data_inserter_.Insert(transformed_range_data,
|
||||||
&submap->low_resolution_hybrid_grid);
|
&submap->low_resolution_hybrid_grid_);
|
||||||
++submap->num_range_data;
|
++submap->num_range_data_;
|
||||||
}
|
}
|
||||||
const Submap* const last_submap = Get(size() - 1);
|
const Submap* const last_submap = Get(size() - 1);
|
||||||
if (last_submap->num_range_data == options_.num_range_data()) {
|
if (last_submap->num_range_data_ == options_.num_range_data()) {
|
||||||
AddSubmap(transform::Rigid3d(range_data.origin.cast<double>(),
|
AddSubmap(transform::Rigid3d(range_data.origin.cast<double>(),
|
||||||
gravity_alignment));
|
gravity_alignment));
|
||||||
}
|
}
|
||||||
|
@ -402,8 +402,8 @@ void Submaps::InsertRangeData(const sensor::RangeData& range_data,
|
||||||
void Submaps::AddSubmap(const transform::Rigid3d& local_pose) {
|
void Submaps::AddSubmap(const transform::Rigid3d& local_pose) {
|
||||||
if (size() > 1) {
|
if (size() > 1) {
|
||||||
Submap* submap = submaps_[size() - 2].get();
|
Submap* submap = submaps_[size() - 2].get();
|
||||||
CHECK(!submap->finished);
|
CHECK(!submap->finished_);
|
||||||
submap->finished = true;
|
submap->finished_ = true;
|
||||||
}
|
}
|
||||||
submaps_.emplace_back(new Submap(options_.high_resolution(),
|
submaps_.emplace_back(new Submap(options_.high_resolution(),
|
||||||
options_.low_resolution(), local_pose));
|
options_.low_resolution(), local_pose));
|
||||||
|
|
|
@ -47,17 +47,30 @@ void InsertIntoProbabilityGrid(
|
||||||
proto::SubmapsOptions CreateSubmapsOptions(
|
proto::SubmapsOptions CreateSubmapsOptions(
|
||||||
common::LuaParameterDictionary* parameter_dictionary);
|
common::LuaParameterDictionary* parameter_dictionary);
|
||||||
|
|
||||||
struct Submap : public mapping::Submap {
|
class Submap : public mapping::Submap {
|
||||||
|
public:
|
||||||
Submap(float high_resolution, float low_resolution,
|
Submap(float high_resolution, float low_resolution,
|
||||||
const transform::Rigid3d& local_pose);
|
const transform::Rigid3d& local_pose);
|
||||||
|
|
||||||
HybridGrid high_resolution_hybrid_grid;
|
const HybridGrid& high_resolution_hybrid_grid() const {
|
||||||
HybridGrid low_resolution_hybrid_grid;
|
return high_resolution_hybrid_grid_;
|
||||||
bool finished = false;
|
}
|
||||||
|
const HybridGrid& low_resolution_hybrid_grid() const {
|
||||||
|
return low_resolution_hybrid_grid_;
|
||||||
|
}
|
||||||
|
const bool finished() const { return finished_; }
|
||||||
|
|
||||||
void ToResponseProto(
|
void ToResponseProto(
|
||||||
const transform::Rigid3d& global_submap_pose,
|
const transform::Rigid3d& global_submap_pose,
|
||||||
mapping::proto::SubmapQuery::Response* response) const override;
|
mapping::proto::SubmapQuery::Response* response) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// TODO(hrapp): Remove friend declaration.
|
||||||
|
friend class Submaps;
|
||||||
|
|
||||||
|
HybridGrid high_resolution_hybrid_grid_;
|
||||||
|
HybridGrid low_resolution_hybrid_grid_;
|
||||||
|
bool finished_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A container of Submaps.
|
// A container of Submaps.
|
||||||
|
|
Loading…
Reference in New Issue