Expose complete poses in 2D SLAM. (#498)

This changes the trajectory nodes to contain the complete 'pose'
including 'tracking_to_tracking_2d' applied already. Similar for
the 'zbar_ij' as it is returned by 'constraints()'. This allows
2D and 3D to be handled in the same way.
master
Wolfgang Hess 2017-09-01 15:40:21 +02:00 committed by GitHub
parent 5673334f0e
commit e3b6f0afc5
5 changed files with 25 additions and 18 deletions

View File

@ -183,9 +183,7 @@ void MapBuilder::SerializeState(io::ProtoStreamWriter* const writer) {
range_data_proto->mutable_node_id()->set_node_index(node_index); range_data_proto->mutable_node_id()->set_node_index(node_index);
const auto& data = *node_data[trajectory_id][node_index].constant_data; const auto& data = *node_data[trajectory_id][node_index].constant_data;
*range_data_proto->mutable_range_data() = *range_data_proto->mutable_range_data() =
sensor::ToProto(sensor::Compress(sensor::TransformRangeData( sensor::ToProto(data.range_data);
sensor::Decompress(data.range_data),
data.tracking_to_pose.inverse().cast<float>())));
// TODO(whess): Only enable optionally? Resulting pbstream files will be // TODO(whess): Only enable optionally? Resulting pbstream files will be
// a lot larger now. // a lot larger now.
writer->WriteProto(proto); writer->WriteProto(proto);

View File

@ -84,8 +84,7 @@ proto::SparsePoseGraph SparsePoseGraph::ToProto() {
auto* node_proto = trajectory_proto->add_node(); auto* node_proto = trajectory_proto->add_node();
node_proto->set_timestamp( node_proto->set_timestamp(
common::ToUniversal(node.constant_data->time)); common::ToUniversal(node.constant_data->time));
*node_proto->mutable_pose() = transform::ToProto( *node_proto->mutable_pose() = transform::ToProto(node.pose);
node.pose * node.constant_data->tracking_to_pose);
} }
} }
@ -107,10 +106,8 @@ proto::SparsePoseGraph SparsePoseGraph::ToProto() {
for (const auto& constraint : constraints()) { for (const auto& constraint : constraints()) {
auto* const constraint_proto = proto.add_constraint(); auto* const constraint_proto = proto.add_constraint();
const auto& node = all_trajectory_nodes.at(constraint.node_id.trajectory_id) *constraint_proto->mutable_relative_pose() =
.at(constraint.node_id.node_index); transform::ToProto(constraint.pose.zbar_ij);
*constraint_proto->mutable_relative_pose() = transform::ToProto(
constraint.pose.zbar_ij * node.constant_data->tracking_to_pose);
constraint_proto->set_translation_weight( constraint_proto->set_translation_weight(
constraint.pose.translation_weight); constraint.pose.translation_weight);
constraint_proto->set_rotation_weight(constraint.pose.rotation_weight); constraint_proto->set_rotation_weight(constraint.pose.rotation_weight);

View File

@ -32,7 +32,7 @@ struct TrajectoryNode {
struct Data { struct Data {
common::Time time; common::Time time;
// Range data in 'pose' frame. // Range data in 'tracking' frame. Only used in 3D.
sensor::CompressedRangeData range_data; sensor::CompressedRangeData range_data;
// Used for loop closure in 2D: voxel filtered returns in 'pose' frame. // Used for loop closure in 2D: voxel filtered returns in 'pose' frame.
@ -42,10 +42,9 @@ struct TrajectoryNode {
sensor::PointCloud high_resolution_point_cloud; sensor::PointCloud high_resolution_point_cloud;
sensor::PointCloud low_resolution_point_cloud; sensor::PointCloud low_resolution_point_cloud;
// Transform from the 3D 'tracking' frame to the 'pose' frame of the range // Transforms the 'tracking' frame into a gravity-aligned 'tracking_2d'
// data, which contains roll, pitch and height for 2D. In 3D this is always // frame. Only used in 2D.
// identity. transform::Rigid3d tracking_to_tracking_2d;
transform::Rigid3d tracking_to_pose;
}; };
common::Time time() const { return constant_data->time; } common::Time time() const { return constant_data->time; }

View File

@ -98,7 +98,8 @@ void SparsePoseGraph::AddScan(
const transform::Rigid2d& pose, const int trajectory_id, const transform::Rigid2d& pose, const int trajectory_id,
const std::vector<std::shared_ptr<const Submap>>& insertion_submaps) { const std::vector<std::shared_ptr<const Submap>>& insertion_submaps) {
const transform::Rigid3d optimized_pose( const transform::Rigid3d optimized_pose(
GetLocalToGlobalTransform(trajectory_id) * transform::Embed3D(pose)); GetLocalToGlobalTransform(trajectory_id) * transform::Embed3D(pose) *
constant_data->tracking_to_tracking_2d);
common::MutexLocker locker(&mutex_); common::MutexLocker locker(&mutex_);
trajectory_nodes_.Append( trajectory_nodes_.Append(
@ -445,7 +446,8 @@ void SparsePoseGraph::RunOptimization() {
++node_data_index, ++node_index) { ++node_data_index, ++node_index) {
const mapping::NodeId node_id{trajectory_id, node_index}; const mapping::NodeId node_id{trajectory_id, node_index};
trajectory_nodes_.at(node_id).pose = trajectory_nodes_.at(node_id).pose =
transform::Embed3D(node_data[trajectory_id][node_data_index].pose); transform::Embed3D(node_data[trajectory_id][node_data_index].pose) *
trajectory_nodes_.at(node_id).constant_data->tracking_to_tracking_2d;
} }
// Extrapolate all point cloud poses that were added later. // Extrapolate all point cloud poses that were added later.
const auto local_to_new_global = const auto local_to_new_global =
@ -482,8 +484,19 @@ SparsePoseGraph::GetTrajectoryNodes() {
} }
std::vector<SparsePoseGraph::Constraint> SparsePoseGraph::constraints() { std::vector<SparsePoseGraph::Constraint> SparsePoseGraph::constraints() {
std::vector<Constraint> result;
common::MutexLocker locker(&mutex_); common::MutexLocker locker(&mutex_);
return constraints_; for (const Constraint& constraint : constraints_) {
result.push_back(Constraint{
constraint.submap_id, constraint.node_id,
Constraint::Pose{constraint.pose.zbar_ij *
trajectory_nodes_.at(constraint.node_id)
.constant_data->tracking_to_tracking_2d,
constraint.pose.translation_weight,
constraint.pose.rotation_weight},
constraint.tag});
}
return result;
} }
transform::Rigid3d SparsePoseGraph::GetLocalToGlobalTransform( transform::Rigid3d SparsePoseGraph::GetLocalToGlobalTransform(

View File

@ -213,7 +213,7 @@ LocalTrajectoryBuilder::InsertIntoSubmap(
{}, // 'filtered_point_cloud' is only used in 2D. {}, // 'filtered_point_cloud' is only used in 2D.
high_resolution_point_cloud, high_resolution_point_cloud,
low_resolution_point_cloud, low_resolution_point_cloud,
transform::Rigid3d::Identity()}), {}}), // 'tracking_to_tracking_2d' in only used in 2D.
pose_observation, std::move(insertion_submaps)}); pose_observation, std::move(insertion_submaps)});
} }