12 #include <gtest/gtest.h> 15 #include <test_mrpt_common.h> 28 {{
"graphslam_SE2_in.graph",
"graphslam_SE2_out_good.graph"},
29 {
"graphslam_SE2_in2.graph",
"graphslam_SE2_out_good2.graph"},
30 {
"graphslam_SE2_in3.graph",
"graphslam_SE2_out_good3.graph"}}},
32 {{
"graphslam_SE2_in.graph",
"graphslam_SE2_out_good.graph"},
33 {
"graphslam_SE2pdf_in.graph",
"graphslam_SE2pdf_out_good.graph"}}},
35 {{
"graphslam_SE3_in_torus3D-first100.graph",
36 "graphslam_SE3_out_good_torus3D-first100.graph"},
37 {
"graphslam_SE2_in2.graph",
"graphslam_SE2_out_good2.graph"}}}};
39 template <
class my_graph_t>
41 public ::testing::Test
52 const my_graph_t graph_initial = graph;
59 params[
"max_iterations"] = 100;
64 graph, levmarq_info,
nullptr,
params);
66 const double err_init = graph_initial.chi2();
67 const double err_end = graph.chi2();
68 std::cout <<
"err_init: " << err_init << std::endl;
69 std::cout <<
"err_end: " << err_end << std::endl;
81 const my_graph_t& g1,
const my_graph_t& g2,
82 const double eps_node_pos = 1e-3,
const double eps_edges = 1e-3)
84 EXPECT_EQ(g1.edges.size(), g2.edges.size());
85 EXPECT_EQ(g1.nodes.size(), g2.nodes.size());
88 if (g1.edges.size() != g2.edges.size() ||
89 g1.nodes.size() != g2.nodes.size())
94 typename my_graph_t::const_iterator it1, it2;
95 for (it1 = g1.edges.begin(), it2 = g2.edges.begin();
96 it1 != g1.edges.end(); ++it1, ++it2)
101 (it1->second.getPoseMean().asVectorVal() -
102 it2->second.getPoseMean().asVectorVal())
110 auto itn1 = g1.nodes.cbegin(), itn2 = g2.nodes.cbegin();
111 for (; itn1 != g1.nodes.cend(); ++itn1, ++itn2)
116 (itn1->second.asVectorVal() - itn2->second.asVectorVal())
119 <<
"Poses of keyframe #" << itn1->first
120 <<
" do not match:" << std::endl
121 <<
"- Expected: " << itn2->second << std::endl
122 <<
"- Got : " << itn1->second << std::endl;
132 std::stringstream ss;
133 graph.writeAsText(ss);
135 my_graph_t read_graph;
137 read_graph.readAsText(ss);
139 compare_two_graphs(graph, read_graph);
151 my_graph_t read_graph;
155 compare_two_graphs(graph, read_graph);
164 const string prefix = UNITTEST_BASEDIR + string(
"/tests/");
165 for (
const auto& tst : files_it->second)
167 std::cout <<
"Testing graph type `" << type <<
"`, in_file=`" 168 << std::get<0>(tst) <<
"`" << std::endl;
170 const string in_f = prefix + std::get<0>(tst);
172 const string good_f = prefix + std::get<1>(tst);
175 my_graph_t graph, graph_good;
176 graph.loadFromTextFile(in_f);
177 graph_good.loadFromTextFile(good_f);
178 ASSERT_(graph.nodeCount() > 1);
179 ASSERT_EQ(graph.nodeCount(), graph_good.nodeCount());
180 ASSERT_EQ(graph.edgeCount(), graph_good.edgeCount());
183 const my_graph_t graph_initial = graph;
185 params[
"max_iterations"] = 100;
190 graph, levmarq_info,
nullptr,
params);
193 const double err_init = graph_initial.chi2();
194 const double err_end = graph.chi2();
195 const double err_good = graph_good.chi2();
196 std::cout <<
"err_init: " << err_init << std::endl;
197 std::cout <<
"err_end: " << err_end << std::endl;
198 std::cout <<
"err_good: " << err_good << std::endl;
206 compare_two_graphs(graph, graph_good);
216 #define GRAPHS_TESTS(_TYPE) \ 217 TEST_F(_TYPE, OptimizeSampleRingPath) \ 219 for (int seed = 1; seed <= 3; seed++) \ 221 getRandomGenerator().randomize(seed); \ 222 test_ring_path(#_TYPE); \ 225 TEST_F(_TYPE, BinarySerialization) \ 227 getRandomGenerator().randomize(123); \ 228 test_graph_bin_serialization(); \ 230 TEST_F(_TYPE, WriteReadTextFile) \ 232 getRandomGenerator().randomize(123); \ 233 test_graph_text_serialization(); \ 235 TEST_F(_TYPE, OptimizeCompareKnownSolution) \ 237 test_optimize_compare_known_solution(#_TYPE); \ A namespace of pseudo-random numbers generators of diferent distributions.
EXPECT_LT(out.final_rmse, 3.0)
void test_graph_bin_serialization()
#define GRAPHS_TESTS(_TYPE)
void optimize_graph_spa_levmarq(GRAPH_T &graph, TResultInfoSpaLevMarq &out_info, const std::set< mrpt::graphs::TNodeID > *in_nodes_to_optimize=nullptr, const mrpt::system::TParametersDouble &extra_params=mrpt::system::TParametersDouble(), FEEDBACK_CALLABLE functor_feedback=FEEDBACK_CALLABLE())
Optimize a graph of pose constraints using the Sparse Pose Adjustment (SPA) sparse representation and...
Abstract graph and tree data structures, plus generic graph algorithms.
std::set< std::tuple< std::string, std::string > > in_out_filenames
size_t num_iters
The number of LM iterations executed.
void test_ring_path(const char *className)
mrpt::vision::TStereoCalibParams params
CArchiveStreamBase< STREAM > archiveFrom(STREAM &s)
Helper function to create a templatized wrapper CArchive object for a: MRPT's CStream, std::istream, std::ostream, std::stringstream.
#define ASSERT_(f)
Defines an assertion mechanism.
This base provides a set of functions for maths stuff.
const std::map< std::string, in_out_filenames > inout_graph_files
This CStream derived class allow using a memory buffer as a CStream.
uint64_t Seek(int64_t Offset, CStream::TSeekOrigin Origin=sFromBeginning) override
Introduces a pure virtual method for moving to a specified position in the streamed resource...
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void test_graph_text_serialization()
EXPECT_EQ(out.image_pair_was_used.size(), NUM_IMGS)
Output information for mrpt::graphslam::optimize_graph_spa_levmarq()
static void create_ring_path(my_graph_t &graph, size_t N_VERTEX=50, double DIST_THRES=7, double NODES_XY_MAX=20)
EXPECT_NEAR(out.cam_params.rightCameraPose.x, 0.1194, 0.005)
void compare_two_graphs(const my_graph_t &g1, const my_graph_t &g2, const double eps_node_pos=1e-3, const double eps_edges=1e-3)
#define ASSERT_FILE_EXISTS_(FIL)
void test_optimize_compare_known_solution(const char *type)
double final_total_sq_error
The sum of all the squared errors for every constraint involved in the problem.