Improvement of 2D/3D consistency and cleanup. (#122)

master
Wolfgang Hess 2016-11-11 14:33:06 +01:00 committed by GitHub
parent 97d5cb2a8b
commit 1de387cba9
9 changed files with 44 additions and 40 deletions

View File

@ -118,6 +118,7 @@ google_library(mapping_2d_sparse_pose_graph
common_fixed_ratio_sampler common_fixed_ratio_sampler
common_make_unique common_make_unique
common_math common_math
common_mutex
common_thread_pool common_thread_pool
common_time common_time
kalman_filter_pose_tracker kalman_filter_pose_tracker
@ -131,6 +132,7 @@ google_library(mapping_2d_sparse_pose_graph
sensor_compressed_point_cloud sensor_compressed_point_cloud
sensor_point_cloud sensor_point_cloud
sensor_voxel_filter sensor_voxel_filter
transform_rigid_transform
transform_transform transform_transform
) )

View File

@ -30,7 +30,6 @@
#include "Eigen/Eigenvalues" #include "Eigen/Eigenvalues"
#include "cartographer/common/make_unique.h" #include "cartographer/common/make_unique.h"
#include "cartographer/common/math.h" #include "cartographer/common/math.h"
#include "cartographer/common/time.h"
#include "cartographer/mapping/proto/scan_matching_progress.pb.h" #include "cartographer/mapping/proto/scan_matching_progress.pb.h"
#include "cartographer/mapping/sparse_pose_graph/proto/constraint_builder_options.pb.h" #include "cartographer/mapping/sparse_pose_graph/proto/constraint_builder_options.pb.h"
#include "cartographer/sensor/compressed_point_cloud.h" #include "cartographer/sensor/compressed_point_cloud.h"
@ -101,7 +100,7 @@ void SparsePoseGraph::AddScan(
constant_node_data_->push_back(mapping::TrajectoryNode::ConstantData{ constant_node_data_->push_back(mapping::TrajectoryNode::ConstantData{
time, laser_fan_in_pose, time, laser_fan_in_pose,
Compress(sensor::LaserFan{Eigen::Vector3f::Zero(), {}, {}, {}}), submaps, Compress(sensor::LaserFan{Eigen::Vector3f::Zero(), {}, {}, {}}), submaps,
transform::Rigid3d(tracking_to_pose)}); tracking_to_pose});
trajectory_nodes_.push_back(mapping::TrajectoryNode{ trajectory_nodes_.push_back(mapping::TrajectoryNode{
&constant_node_data_->back(), optimized_pose, &constant_node_data_->back(), optimized_pose,
}); });
@ -126,10 +125,19 @@ void SparsePoseGraph::AddScan(
common::make_unique<common::FixedRatioSampler>( common::make_unique<common::FixedRatioSampler>(
options_.global_sampling_ratio()); options_.global_sampling_ratio());
} }
AddWorkItem(
std::bind(std::mem_fn(&SparsePoseGraph::ComputeConstraintsForScan), this, AddWorkItem([=]() REQUIRES(mutex_) {
j, submaps, matching_submap, insertion_submaps, finished_submap, ComputeConstraintsForScan(j, submaps, matching_submap, insertion_submaps,
pose, covariance)); finished_submap, pose, covariance);
});
}
void SparsePoseGraph::AddWorkItem(std::function<void()> work_item) {
if (scan_queue_ == nullptr) {
work_item();
} else {
scan_queue_->push_back(work_item);
}
} }
void SparsePoseGraph::ComputeConstraintsForOldScans( void SparsePoseGraph::ComputeConstraintsForOldScans(
@ -301,14 +309,6 @@ void SparsePoseGraph::WaitForAllComputations() {
locker.Await([&notification]() { return notification; }); locker.Await([&notification]() { return notification; });
} }
void SparsePoseGraph::AddWorkItem(std::function<void()> work_item) {
if (scan_queue_ == nullptr) {
work_item();
} else {
scan_queue_->push_back(work_item);
}
}
void SparsePoseGraph::RunFinalOptimization() { void SparsePoseGraph::RunFinalOptimization() {
WaitForAllComputations(); WaitForAllComputations();
optimization_problem_.SetMaxNumIterations( optimization_problem_.SetMaxNumIterations(

View File

@ -37,6 +37,7 @@
#include "Eigen/Core" #include "Eigen/Core"
#include "Eigen/Geometry" #include "Eigen/Geometry"
#include "cartographer/common/fixed_ratio_sampler.h" #include "cartographer/common/fixed_ratio_sampler.h"
#include "cartographer/common/mutex.h"
#include "cartographer/common/thread_pool.h" #include "cartographer/common/thread_pool.h"
#include "cartographer/common/time.h" #include "cartographer/common/time.h"
#include "cartographer/kalman_filter/pose_tracker.h" #include "cartographer/kalman_filter/pose_tracker.h"
@ -47,6 +48,7 @@
#include "cartographer/mapping_2d/sparse_pose_graph/optimization_problem.h" #include "cartographer/mapping_2d/sparse_pose_graph/optimization_problem.h"
#include "cartographer/mapping_2d/submaps.h" #include "cartographer/mapping_2d/submaps.h"
#include "cartographer/sensor/point_cloud.h" #include "cartographer/sensor/point_cloud.h"
#include "cartographer/transform/rigid_transform.h"
#include "cartographer/transform/transform.h" #include "cartographer/transform/transform.h"
namespace cartographer { namespace cartographer {
@ -81,7 +83,6 @@ class SparsePoseGraph : public mapping::SparsePoseGraph {
void RunFinalOptimization() override; void RunFinalOptimization() override;
bool HasNewOptimizedPoses() override; bool HasNewOptimizedPoses() override;
mapping::proto::ScanMatchingProgress GetScanMatchingProgress() override; mapping::proto::ScanMatchingProgress GetScanMatchingProgress() override;
std::vector<std::vector<const mapping::Submaps*>> GetConnectedTrajectories() std::vector<std::vector<const mapping::Submaps*>> GetConnectedTrajectories()
override; override;
std::vector<transform::Rigid3d> GetSubmapTransforms( std::vector<transform::Rigid3d> GetSubmapTransforms(
@ -111,6 +112,9 @@ class SparsePoseGraph : public mapping::SparsePoseGraph {
const mapping::Submaps* trajectory = nullptr; const mapping::Submaps* trajectory = nullptr;
}; };
// Handles a new work item.
void AddWorkItem(std::function<void()> work_item) REQUIRES(mutex_);
int GetSubmapIndex(const mapping::Submap* submap) const REQUIRES(mutex_) { int GetSubmapIndex(const mapping::Submap* submap) const REQUIRES(mutex_) {
const auto iterator = submap_indices_.find(submap); const auto iterator = submap_indices_.find(submap);
CHECK(iterator != submap_indices_.end()); CHECK(iterator != submap_indices_.end());
@ -145,9 +149,6 @@ class SparsePoseGraph : public mapping::SparsePoseGraph {
// optimization being run at a time. // optimization being run at a time.
void RunOptimization() EXCLUDES(mutex_); void RunOptimization() EXCLUDES(mutex_);
// Handles a new 'work_item'.
void AddWorkItem(std::function<void()> work_item) REQUIRES(mutex_);
// Adds extrapolated transforms, so that there are transforms for all submaps. // Adds extrapolated transforms, so that there are transforms for all submaps.
std::vector<transform::Rigid3d> ExtrapolateSubmapTransforms( std::vector<transform::Rigid3d> ExtrapolateSubmapTransforms(
const std::vector<transform::Rigid2d>& submap_transforms, const std::vector<transform::Rigid2d>& submap_transforms,

View File

@ -244,6 +244,7 @@ google_library(mapping_3d_sparse_pose_graph
mapping_sparse_pose_graph mapping_sparse_pose_graph
mapping_sparse_pose_graph_proto_constraint_builder_options mapping_sparse_pose_graph_proto_constraint_builder_options
mapping_trajectory_connectivity mapping_trajectory_connectivity
sensor_compressed_point_cloud
sensor_point_cloud sensor_point_cloud
sensor_voxel_filter sensor_voxel_filter
transform_rigid_transform transform_rigid_transform

View File

@ -30,9 +30,9 @@
#include "Eigen/Eigenvalues" #include "Eigen/Eigenvalues"
#include "cartographer/common/make_unique.h" #include "cartographer/common/make_unique.h"
#include "cartographer/common/math.h" #include "cartographer/common/math.h"
#include "cartographer/common/mutex.h"
#include "cartographer/mapping/proto/scan_matching_progress.pb.h" #include "cartographer/mapping/proto/scan_matching_progress.pb.h"
#include "cartographer/mapping/sparse_pose_graph/proto/constraint_builder_options.pb.h" #include "cartographer/mapping/sparse_pose_graph/proto/constraint_builder_options.pb.h"
#include "cartographer/sensor/compressed_point_cloud.h"
#include "cartographer/sensor/voxel_filter.h" #include "cartographer/sensor/voxel_filter.h"
#include "glog/logging.h" #include "glog/logging.h"
@ -176,7 +176,7 @@ void SparsePoseGraph::ComputeConstraintsForScan(
submap_transforms_[matching_index] * submap_transforms_[matching_index] *
matching_submap->local_pose().inverse() * pose; matching_submap->local_pose().inverse() * pose;
CHECK_EQ(scan_index, optimization_problem_.node_data().size()); CHECK_EQ(scan_index, optimization_problem_.node_data().size());
optimization_problem_.AddTrajectoryNode(time, pose, optimized_pose); optimization_problem_.AddTrajectoryNode(time, optimized_pose);
for (const Submap* submap : insertion_submaps) { for (const Submap* submap : insertion_submaps) {
const int submap_index = GetSubmapIndex(submap); const int submap_index = GetSubmapIndex(submap);
CHECK(!submap_states_[submap_index].finished); CHECK(!submap_states_[submap_index].finished);
@ -247,7 +247,7 @@ void SparsePoseGraph::ComputeConstraintsForScan(
run_loop_closure_ = true; run_loop_closure_ = true;
// If there is a 'scan_queue_' already, some other thread will take care. // If there is a 'scan_queue_' already, some other thread will take care.
if (scan_queue_ == nullptr) { if (scan_queue_ == nullptr) {
scan_queue_.reset(new std::deque<std::function<void()>>); scan_queue_ = common::make_unique<std::deque<std::function<void()>>>();
HandleScanQueue(); HandleScanQueue();
} }
} }
@ -338,8 +338,7 @@ void SparsePoseGraph::RunOptimization() {
const auto& node_data = optimization_problem_.node_data(); const auto& node_data = optimization_problem_.node_data();
const size_t num_optimized_poses = node_data.size(); const size_t num_optimized_poses = node_data.size();
for (size_t i = 0; i != num_optimized_poses; ++i) { for (size_t i = 0; i != num_optimized_poses; ++i) {
trajectory_nodes_[i].pose = trajectory_nodes_[i].pose = node_data[i].point_cloud_pose;
transform::Rigid3d(node_data[i].point_cloud_pose);
} }
// Extrapolate all point cloud poses that were added later. // Extrapolate all point cloud poses that were added later.
std::unordered_map<const mapping::Submaps*, transform::Rigid3d> std::unordered_map<const mapping::Submaps*, transform::Rigid3d>

View File

@ -41,6 +41,7 @@
#include "cartographer/common/thread_pool.h" #include "cartographer/common/thread_pool.h"
#include "cartographer/common/time.h" #include "cartographer/common/time.h"
#include "cartographer/kalman_filter/pose_tracker.h" #include "cartographer/kalman_filter/pose_tracker.h"
#include "cartographer/mapping/proto/scan_matching_progress.pb.h"
#include "cartographer/mapping/sparse_pose_graph.h" #include "cartographer/mapping/sparse_pose_graph.h"
#include "cartographer/mapping/trajectory_connectivity.h" #include "cartographer/mapping/trajectory_connectivity.h"
#include "cartographer/mapping_3d/sparse_pose_graph/constraint_builder.h" #include "cartographer/mapping_3d/sparse_pose_graph/constraint_builder.h"

View File

@ -84,10 +84,8 @@ void OptimizationProblem::AddImuData(common::Time time,
} }
void OptimizationProblem::AddTrajectoryNode( void OptimizationProblem::AddTrajectoryNode(
common::Time time, const transform::Rigid3d& initial_point_cloud_pose, common::Time time, const transform::Rigid3d& point_cloud_pose) {
const transform::Rigid3d& point_cloud_pose) { node_data_.push_back(NodeData{time, point_cloud_pose});
node_data_.push_back(
NodeData{time, initial_point_cloud_pose, point_cloud_pose});
} }
void OptimizationProblem::SetMaxNumIterations(const int32 max_num_iterations) { void OptimizationProblem::SetMaxNumIterations(const int32 max_num_iterations) {

View File

@ -37,7 +37,6 @@ namespace sparse_pose_graph {
struct NodeData { struct NodeData {
common::Time time; common::Time time;
transform::Rigid3d initial_point_cloud_pose;
transform::Rigid3d point_cloud_pose; transform::Rigid3d point_cloud_pose;
}; };
@ -57,7 +56,6 @@ class OptimizationProblem {
void AddImuData(common::Time time, const Eigen::Vector3d& linear_acceleration, void AddImuData(common::Time time, const Eigen::Vector3d& linear_acceleration,
const Eigen::Vector3d& angular_velocity); const Eigen::Vector3d& angular_velocity);
void AddTrajectoryNode(common::Time time, void AddTrajectoryNode(common::Time time,
const transform::Rigid3d& initial_point_cloud_pose,
const transform::Rigid3d& point_cloud_pose); const transform::Rigid3d& point_cloud_pose);
void SetMaxNumIterations(int32 max_num_iterations); void SetMaxNumIterations(int32 max_num_iterations);

View File

@ -126,7 +126,7 @@ TEST_F(OptimizationProblemTest, ReducesNoise) {
AddNoise(node.ground_truth_pose, node.noise); AddNoise(node.ground_truth_pose, node.noise);
optimization_problem_.AddImuData(now, Eigen::Vector3d::UnitZ() * 9.81, optimization_problem_.AddImuData(now, Eigen::Vector3d::UnitZ() * 9.81,
Eigen::Vector3d::Zero()); Eigen::Vector3d::Zero());
optimization_problem_.AddTrajectoryNode(now, pose, pose); optimization_problem_.AddTrajectoryNode(now, pose);
now += common::FromSeconds(0.01); now += common::FromSeconds(0.01);
} }
@ -153,29 +153,33 @@ TEST_F(OptimizationProblemTest, ReducesNoise) {
std::vector<transform::Rigid3d> submap_transforms = { std::vector<transform::Rigid3d> submap_transforms = {
kSubmap0Transform, kSubmap0Transform, kSubmap2Transform}; kSubmap0Transform, kSubmap0Transform, kSubmap2Transform};
double translation_error_before = 0.;
double rotation_error_before = 0.;
const auto& node_data = optimization_problem_.node_data();
for (int j = 0; j != kNumNodes; ++j) {
translation_error_before += (test_data[j].ground_truth_pose.translation() -
node_data[j].point_cloud_pose.translation())
.norm();
rotation_error_before +=
transform::GetAngle(test_data[j].ground_truth_pose.inverse() *
node_data[j].point_cloud_pose);
}
optimization_problem_.Solve(constraints, kSubmap0Transform, trajectories, optimization_problem_.Solve(constraints, kSubmap0Transform, trajectories,
&submap_transforms); &submap_transforms);
double translation_error_before = 0.;
double translation_error_after = 0.; double translation_error_after = 0.;
double rotation_error_before = 0.;
double rotation_error_after = 0.; double rotation_error_after = 0.;
const auto& node_data = optimization_problem_.node_data();
for (int j = 0; j != kNumNodes; ++j) { for (int j = 0; j != kNumNodes; ++j) {
translation_error_before +=
(test_data[j].ground_truth_pose.translation() -
node_data[j].initial_point_cloud_pose.translation())
.norm();
translation_error_after += (test_data[j].ground_truth_pose.translation() - translation_error_after += (test_data[j].ground_truth_pose.translation() -
node_data[j].point_cloud_pose.translation()) node_data[j].point_cloud_pose.translation())
.norm(); .norm();
rotation_error_before +=
transform::GetAngle(test_data[j].ground_truth_pose.inverse() *
node_data[j].initial_point_cloud_pose);
rotation_error_after += rotation_error_after +=
transform::GetAngle(test_data[j].ground_truth_pose.inverse() * transform::GetAngle(test_data[j].ground_truth_pose.inverse() *
node_data[j].point_cloud_pose); node_data[j].point_cloud_pose);
} }
EXPECT_GT(0.8 * translation_error_before, translation_error_after); EXPECT_GT(0.8 * translation_error_before, translation_error_after);
EXPECT_GT(0.8 * rotation_error_before, rotation_error_after); EXPECT_GT(0.8 * rotation_error_before, rotation_error_after);
} }