Change fixed_frame_pose_data_ to MapByTime. (#662)
parent
fd5003b69b
commit
3ec583a327
|
@ -47,6 +47,32 @@ namespace cartographer {
|
|||
namespace mapping_3d {
|
||||
namespace sparse_pose_graph {
|
||||
|
||||
namespace {
|
||||
|
||||
// For odometry and fixed frame pose.
|
||||
template <typename MapByTimeType>
|
||||
std::unique_ptr<transform::Rigid3d> Interpolate(
|
||||
const MapByTimeType& map_by_time, const int trajectory_id,
|
||||
const common::Time time) {
|
||||
const auto it = map_by_time.lower_bound(trajectory_id, time);
|
||||
if (it == map_by_time.EndOfTrajectory(trajectory_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (it == map_by_time.BeginOfTrajectory(trajectory_id)) {
|
||||
if (it->time == time) {
|
||||
return common::make_unique<transform::Rigid3d>(it->pose);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
const auto prev_it = std::prev(it);
|
||||
return common::make_unique<transform::Rigid3d>(
|
||||
Interpolate(transform::TimestampedTransform{prev_it->time, prev_it->pose},
|
||||
transform::TimestampedTransform{it->time, it->pose}, time)
|
||||
.transform);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OptimizationProblem::OptimizationProblem(
|
||||
const mapping::sparse_pose_graph::proto::OptimizationProblemOptions&
|
||||
options,
|
||||
|
@ -68,11 +94,7 @@ void OptimizationProblem::AddOdometerData(
|
|||
void OptimizationProblem::AddFixedFramePoseData(
|
||||
const int trajectory_id,
|
||||
const sensor::FixedFramePoseData& fixed_frame_pose_data) {
|
||||
CHECK_GE(trajectory_id, 0);
|
||||
fixed_frame_pose_data_.resize(std::max(
|
||||
fixed_frame_pose_data_.size(), static_cast<size_t>(trajectory_id) + 1));
|
||||
fixed_frame_pose_data_[trajectory_id].Push(fixed_frame_pose_data.time,
|
||||
fixed_frame_pose_data.pose);
|
||||
fixed_frame_pose_data_.Append(trajectory_id, fixed_frame_pose_data);
|
||||
}
|
||||
|
||||
void OptimizationProblem::AddTrajectoryNode(
|
||||
|
@ -98,6 +120,7 @@ void OptimizationProblem::InsertTrajectoryNode(
|
|||
void OptimizationProblem::TrimTrajectoryNode(const mapping::NodeId& node_id) {
|
||||
imu_data_.Trim(node_data_, node_id);
|
||||
odometry_data_.Trim(node_data_, node_id);
|
||||
fixed_frame_pose_data_.Trim(node_data_, node_id);
|
||||
node_data_.Trim(node_id);
|
||||
}
|
||||
|
||||
|
@ -346,23 +369,25 @@ void OptimizationProblem::Solve(const std::vector<Constraint>& constraints,
|
|||
std::deque<CeresPose> C_fixed_frames;
|
||||
for (auto node_it = node_data_.begin(); node_it != node_data_.end();) {
|
||||
const int trajectory_id = node_it->id.trajectory_id;
|
||||
if (trajectory_id >= static_cast<int>(fixed_frame_pose_data_.size())) {
|
||||
break;
|
||||
}
|
||||
bool fixed_frame_pose_initialized = false;
|
||||
|
||||
const auto trajectory_end = node_data_.EndOfTrajectory(trajectory_id);
|
||||
if (!fixed_frame_pose_data_.HasTrajectory(trajectory_id)) {
|
||||
node_it = trajectory_end;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool fixed_frame_pose_initialized = false;
|
||||
for (; node_it != trajectory_end; ++node_it) {
|
||||
const mapping::NodeId node_id = node_it->id;
|
||||
const NodeData& node_data = node_it->data;
|
||||
|
||||
if (!fixed_frame_pose_data_.at(trajectory_id).Has(node_data.time)) {
|
||||
const std::unique_ptr<transform::Rigid3d> fixed_frame_pose =
|
||||
Interpolate(fixed_frame_pose_data_, trajectory_id, node_data.time);
|
||||
if (fixed_frame_pose == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const mapping::SparsePoseGraph::Constraint::Pose constraint_pose{
|
||||
fixed_frame_pose_data_.at(trajectory_id).Lookup(node_data.time),
|
||||
options_.fixed_frame_pose_translation_weight(),
|
||||
*fixed_frame_pose, options_.fixed_frame_pose_translation_weight(),
|
||||
options_.fixed_frame_pose_rotation_weight()};
|
||||
|
||||
if (!fixed_frame_pose_initialized) {
|
||||
|
@ -440,33 +465,14 @@ const sensor::MapByTime<sensor::ImuData>& OptimizationProblem::imu_data()
|
|||
return imu_data_;
|
||||
}
|
||||
|
||||
std::unique_ptr<transform::Rigid3d> OptimizationProblem::InterpolateOdometry(
|
||||
const int trajectory_id, const common::Time time) const {
|
||||
const auto it = odometry_data_.lower_bound(trajectory_id, time);
|
||||
if (it == odometry_data_.EndOfTrajectory(trajectory_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (it == odometry_data_.BeginOfTrajectory(trajectory_id)) {
|
||||
if (it->time == time) {
|
||||
return common::make_unique<transform::Rigid3d>(it->pose);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
const auto prev_it = std::prev(it);
|
||||
return common::make_unique<transform::Rigid3d>(
|
||||
Interpolate(transform::TimestampedTransform{prev_it->time, prev_it->pose},
|
||||
transform::TimestampedTransform{it->time, it->pose}, time)
|
||||
.transform);
|
||||
}
|
||||
|
||||
transform::Rigid3d OptimizationProblem::ComputeRelativePose(
|
||||
const int trajectory_id, const NodeData& first_node_data,
|
||||
const NodeData& second_node_data) const {
|
||||
if (odometry_data_.HasTrajectory(trajectory_id)) {
|
||||
const std::unique_ptr<transform::Rigid3d> first_node_odometry =
|
||||
InterpolateOdometry(trajectory_id, first_node_data.time);
|
||||
Interpolate(odometry_data_, trajectory_id, first_node_data.time);
|
||||
const std::unique_ptr<transform::Rigid3d> second_node_odometry =
|
||||
InterpolateOdometry(trajectory_id, second_node_data.time);
|
||||
Interpolate(odometry_data_, trajectory_id, second_node_data.time);
|
||||
if (first_node_odometry != nullptr && second_node_odometry != nullptr) {
|
||||
return first_node_odometry->inverse() * (*second_node_odometry);
|
||||
}
|
||||
|
|
|
@ -96,8 +96,6 @@ class OptimizationProblem {
|
|||
const sensor::MapByTime<sensor::ImuData>& imu_data() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<transform::Rigid3d> InterpolateOdometry(
|
||||
int trajectory_id, common::Time time) const;
|
||||
// Uses odometry if available, otherwise the local SLAM results.
|
||||
transform::Rigid3d ComputeRelativePose(
|
||||
int trajectory_id, const NodeData& first_node_data,
|
||||
|
@ -114,8 +112,8 @@ class OptimizationProblem {
|
|||
mapping::MapById<mapping::SubmapId, SubmapData> submap_data_;
|
||||
sensor::MapByTime<sensor::ImuData> imu_data_;
|
||||
sensor::MapByTime<sensor::OdometryData> odometry_data_;
|
||||
sensor::MapByTime<sensor::FixedFramePoseData> fixed_frame_pose_data_;
|
||||
std::vector<TrajectoryData> trajectory_data_;
|
||||
std::vector<transform::TransformInterpolationBuffer> fixed_frame_pose_data_;
|
||||
};
|
||||
|
||||
} // namespace sparse_pose_graph
|
||||
|
|
|
@ -52,6 +52,9 @@ class MapByTime {
|
|||
const mapping::NodeId& node_id) {
|
||||
const int trajectory_id = node_id.trajectory_id;
|
||||
CHECK_GE(trajectory_id, 0);
|
||||
if (data_.count(trajectory_id) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Data only important between 'gap_start' and 'gap_end' is no longer
|
||||
// needed. We retain the first and last data of the gap so that
|
||||
|
@ -68,7 +71,7 @@ class MapByTime {
|
|||
: common::Time::max();
|
||||
CHECK_LT(gap_start, gap_end);
|
||||
|
||||
auto& trajectory = data_[trajectory_id];
|
||||
auto& trajectory = data_.at(trajectory_id);
|
||||
auto data_it = trajectory.lower_bound(gap_start);
|
||||
auto data_end = trajectory.upper_bound(gap_end);
|
||||
if (data_it == data_end) {
|
||||
|
|
|
@ -88,6 +88,15 @@ TEST(MapByTimeTest, Trimming) {
|
|||
EXPECT_FALSE(map_by_time.HasTrajectory(42));
|
||||
}
|
||||
|
||||
TEST(MapByTimeTest, TrimmingDoesNotCreateTrajectory) {
|
||||
MapByTime<Data> map_by_time;
|
||||
EXPECT_FALSE(map_by_time.HasTrajectory(42));
|
||||
mapping::MapById<mapping::NodeId, NodeData> map_by_id;
|
||||
map_by_id.Append(42, NodeData{CreateTime(42)});
|
||||
map_by_time.Trim(map_by_id, mapping::NodeId{42, 0});
|
||||
EXPECT_FALSE(map_by_time.HasTrajectory(42));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace sensor
|
||||
} // namespace cartographer
|
||||
|
|
Loading…
Reference in New Issue