20 #include "cartographer/mapping/proto/serialization.pb.h" 24 #include "gmock/gmock.h" 25 #include "google/protobuf/util/message_differencer.h" 31 using ::cartographer::mapping::optimization::OptimizationProblem3D;
32 using ::cartographer::mapping::optimization::proto::OptimizationProblemOptions;
35 class MockOptimizationProblem3D :
public OptimizationProblem3D {
37 MockOptimizationProblem3D()
38 : OptimizationProblem3D(OptimizationProblemOptions{}) {}
39 ~MockOptimizationProblem3D()
override =
default;
42 void(
const std::vector<Constraint> &,
const std::set<int> &,
43 const std::map<std::string, LandmarkNode> &));
46 class PoseGraph3DForTesting :
public PoseGraph3D {
48 PoseGraph3DForTesting(
49 const proto::PoseGraphOptions &options,
50 std::unique_ptr<optimization::OptimizationProblem3D> optimization_problem,
51 common::ThreadPool *thread_pool)
52 : PoseGraph3D(options, std::move(optimization_problem), thread_pool) {}
57 class PoseGraph3DTest :
public ::testing::Test {
62 void SetUp()
override {
63 const std::string kPoseGraphLua = R
"text( 64 include "pose_graph.lua" 65 return POSE_GRAPH)text"; 70 void BuildPoseGraph() {
71 auto optimization_problem =
72 common::make_unique<optimization::OptimizationProblem3D>(
74 pose_graph_ = common::make_unique<PoseGraph3DForTesting>(
79 void BuildPoseGraphWithFakeOptimization() {
80 auto optimization_problem =
81 common::make_unique<MockOptimizationProblem3D>();
82 pose_graph_ = common::make_unique<PoseGraph3DForTesting>(
92 TEST_F(PoseGraph3DTest, Empty) {
94 pose_graph_->WaitForAllComputations();
95 EXPECT_TRUE(pose_graph_->GetAllSubmapData().empty());
96 EXPECT_TRUE(pose_graph_->constraints().empty());
97 EXPECT_TRUE(pose_graph_->GetConnectedTrajectories().empty());
98 EXPECT_TRUE(pose_graph_->GetAllSubmapPoses().empty());
99 EXPECT_TRUE(pose_graph_->GetTrajectoryNodes().empty());
100 EXPECT_TRUE(pose_graph_->GetTrajectoryNodePoses().empty());
101 EXPECT_TRUE(pose_graph_->GetTrajectoryData().empty());
102 proto::PoseGraph empty_proto;
103 EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
104 pose_graph_->ToProto(), empty_proto));
107 TEST_F(PoseGraph3DTest, BasicSerialization) {
109 proto::PoseGraph proto;
112 pose_graph_->AddNodeFromProto(Rigid3d::Identity(), fake_node);
115 pose_graph_->AddSubmapFromProto(Rigid3d::Identity(), fake_submap);
118 pose_graph_->AddSerializedConstraints(
FromProto(proto.constraint()));
121 pose_graph_->SetLandmarkPose(
"landmark_id", Rigid3d::Identity());
122 pose_graph_->WaitForAllComputations();
123 proto::PoseGraph actual_proto = pose_graph_->ToProto();
124 EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
125 proto.constraint(0), actual_proto.constraint(0)));
126 EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
127 proto.trajectory(0).node(0), actual_proto.trajectory(0).node(0)));
128 EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
129 proto.trajectory(0).submap(0), actual_proto.trajectory(0).submap(0)));
130 EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
131 proto.trajectory(0), actual_proto.trajectory(0)));
132 EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
133 proto.landmark_poses(0), actual_proto.landmark_poses(0)));
135 google::protobuf::util::MessageDifferencer::Equals(proto, actual_proto));
138 TEST_F(PoseGraph3DTest, PureLocalizationTrimmer) {
139 BuildPoseGraphWithFakeOptimization();
140 const int trajectory_id = 2;
141 const int num_submaps_to_create = 5;
142 const int num_submaps_to_keep = 3;
143 const int num_nodes_per_submap = 2;
144 for (
int i = 0; i < num_submaps_to_create; ++i) {
145 int submap_index = (i < 3) ? 42 + i : 100 + i;
147 pose_graph_->AddSubmapFromProto(Rigid3d::Identity(), submap);
148 for (
int j = 0; j < num_nodes_per_submap; ++j) {
149 int node_index = 7 + num_nodes_per_submap * submap_index + j;
151 pose_graph_->AddNodeFromProto(Rigid3d::Identity(), node);
152 proto::PoseGraph proto;
156 constraint.set_tag(proto::PoseGraph::Constraint::INTRA_SUBMAP);
158 pose_graph_->AddSerializedConstraints(
FromProto(proto.constraint()));
161 pose_graph_->AddTrimmer(common::make_unique<PureLocalizationTrimmer>(
162 trajectory_id, num_submaps_to_keep));
163 pose_graph_->WaitForAllComputations();
165 pose_graph_->GetAllSubmapPoses().SizeOfTrajectoryOrZero(trajectory_id),
166 num_submaps_to_create);
168 pose_graph_->GetAllSubmapData().SizeOfTrajectoryOrZero(trajectory_id),
169 num_submaps_to_create);
171 pose_graph_->GetTrajectoryNodes().SizeOfTrajectoryOrZero(trajectory_id),
172 num_nodes_per_submap * num_submaps_to_create);
173 EXPECT_EQ(pose_graph_->GetTrajectoryNodePoses().SizeOfTrajectoryOrZero(
175 num_nodes_per_submap * num_submaps_to_create);
176 EXPECT_EQ(pose_graph_->constraints().size(),
177 num_nodes_per_submap * num_submaps_to_create);
178 for (
int i = 0; i < 2; ++i) {
179 pose_graph_->RunFinalOptimization();
181 pose_graph_->GetAllSubmapPoses().SizeOfTrajectoryOrZero(trajectory_id),
182 num_submaps_to_keep);
184 pose_graph_->GetAllSubmapData().SizeOfTrajectoryOrZero(trajectory_id),
185 num_submaps_to_keep);
187 pose_graph_->GetTrajectoryNodes().SizeOfTrajectoryOrZero(trajectory_id),
188 num_nodes_per_submap * num_submaps_to_keep);
189 EXPECT_EQ(pose_graph_->GetTrajectoryNodePoses().SizeOfTrajectoryOrZero(
191 num_nodes_per_submap * num_submaps_to_keep);
192 EXPECT_EQ(pose_graph_->constraints().size(),
193 num_nodes_per_submap * num_submaps_to_keep);
197 class EvenSubmapTrimmer :
public PoseGraphTrimmer {
199 explicit EvenSubmapTrimmer(
int trajectory_id)
202 void Trim(Trimmable *pose_graph)
override {
204 for (
const auto submap_id : submap_ids) {
205 if (submap_id.submap_index % 2 == 0) {
206 pose_graph->MarkSubmapAsTrimmed(submap_id);
211 bool IsFinished()
override {
return false; }
217 TEST_F(PoseGraph3DTest, EvenSubmapTrimmer) {
218 BuildPoseGraphWithFakeOptimization();
219 const int trajectory_id = 2;
220 const int num_submaps_to_keep = 10;
221 const int num_submaps_to_create = 2 * num_submaps_to_keep;
222 const int num_nodes_per_submap = 3;
223 for (
int i = 0; i < num_submaps_to_create; ++i) {
224 int submap_index = 42 + i;
226 pose_graph_->AddSubmapFromProto(Rigid3d::Identity(), submap);
227 for (
int j = 0; j < num_nodes_per_submap; ++j) {
228 int node_index = 7 + num_nodes_per_submap * i + j;
230 pose_graph_->AddNodeFromProto(Rigid3d::Identity(), node);
231 proto::PoseGraph proto;
233 constraint.set_tag(proto::PoseGraph::Constraint::INTRA_SUBMAP);
235 pose_graph_->AddSerializedConstraints(
FromProto(proto.constraint()));
238 pose_graph_->AddTrimmer(
239 common::make_unique<EvenSubmapTrimmer>(trajectory_id));
240 pose_graph_->WaitForAllComputations();
242 pose_graph_->GetAllSubmapPoses().SizeOfTrajectoryOrZero(trajectory_id),
243 num_submaps_to_create);
245 pose_graph_->GetAllSubmapData().SizeOfTrajectoryOrZero(trajectory_id),
246 num_submaps_to_create);
248 pose_graph_->GetTrajectoryNodes().SizeOfTrajectoryOrZero(trajectory_id),
249 num_nodes_per_submap * num_submaps_to_create);
250 EXPECT_EQ(pose_graph_->GetTrajectoryNodePoses().SizeOfTrajectoryOrZero(
252 num_nodes_per_submap * num_submaps_to_create);
253 EXPECT_EQ(pose_graph_->constraints().size(),
254 num_nodes_per_submap * num_submaps_to_create);
255 for (
int i = 0; i < 2; ++i) {
256 pose_graph_->RunFinalOptimization();
258 pose_graph_->GetAllSubmapPoses().SizeOfTrajectoryOrZero(trajectory_id),
259 num_submaps_to_keep);
261 pose_graph_->GetAllSubmapData().SizeOfTrajectoryOrZero(trajectory_id),
262 num_submaps_to_keep);
264 pose_graph_->GetTrajectoryNodes().SizeOfTrajectoryOrZero(trajectory_id),
265 num_nodes_per_submap * num_submaps_to_keep);
266 EXPECT_EQ(pose_graph_->GetTrajectoryNodePoses().SizeOfTrajectoryOrZero(
268 num_nodes_per_submap * num_submaps_to_keep);
269 EXPECT_EQ(pose_graph_->constraints().size(),
270 num_nodes_per_submap * num_submaps_to_keep);
PoseGraph::Constraint::Tag FromProto(const proto::PoseGraph::Constraint::Tag &proto)
void WaitForAllComputations() EXCLUDES(mutex_)
proto::PoseGraph::Constraint CreateFakeConstraint(const proto::Node &node, const proto::Submap &submap)
_Unique_if< T >::_Single_object make_unique(Args &&... args)
void AddToProtoGraph(const proto::Node &node_data, proto::PoseGraph *pose_graph)
proto::PoseGraphOptions pose_graph_options_
std::unique_ptr< common::ThreadPool > thread_pool_
proto::PoseGraphOptions CreatePoseGraphOptions(common::LuaParameterDictionary *const parameter_dictionary)
proto::Submap CreateFakeSubmap3D(int trajectory_id, int submap_index)
std::unique_ptr< PoseGraph3DForTesting > pose_graph_
proto::PoseGraph::LandmarkPose CreateFakeLandmark(const std::string &landmark_id, const transform::Rigid3d &global_pose)
proto::Node CreateFakeNode(int trajectory_id, int node_index)
std::unique_ptr<::cartographer::common::LuaParameterDictionary > ResolveLuaParameters(const std::string &lua_code)