48 template <
class GRAPH,
bool EDGES_ARE_PDF = GRAPH::edge_t::is_PDF_val>
55 template <
class GRAPH>
63 const typename GRAPH::global_poses_t& real_poses, GRAPH& graph,
73 typename GRAPH::edge_t RelativePose(
74 real_poses.find(to)->second - real_poses.find(from)->second);
75 graph.insertEdge(from, to, RelativePose);
79 template <
class GRAPH>
87 const typename GRAPH::global_poses_t& real_poses, GRAPH& graph,
90 typename GRAPH::edge_t RelativePose(
91 real_poses.find(to)->second - real_poses.find(from)->second,
93 graph.insertEdge(from, to, RelativePose);
102 template <
class my_graph_t>
105 template <
class GRAPH_T>
106 static void my_levmarq_feedback(
107 const GRAPH_T& graph,
const size_t iter,
const size_t max_iter,
108 const double cur_sq_error)
111 if ((iter % 100) == 0)
112 cout <<
"Progress: " << iter <<
" / " << max_iter
113 <<
", total sq err = " << cur_sq_error << endl;
119 void run(
bool add_extra_tightening_edge)
125 typename my_graph_t::global_poses_t real_node_poses;
136 const size_t N_VERTEX = 50;
137 const double DIST_THRES = 7;
138 const double NODES_XY_MAX = 20;
144 for (
TNodeID j = 0; j < N_VERTEX; j++)
147 static double ang = 2 *
M_PI / N_VERTEX;
148 const double R = NODES_XY_MAX + 2 * (j % 2 ? 1 : -1);
149 CPose2D p(
R * cos(ang * j),
R * sin(ang * j), ang);
152 real_node_poses[j] =
p;
167 typename edge_adder_t::cov_t inf_matrix;
169 edge_adder_t::cov_t::RowsAtCompileTime,
175 for (
TNodeID i = 0; i < N_VERTEX; i++)
177 for (
TNodeID j = i + 1; j < N_VERTEX; j++)
179 if (real_node_poses[i].distanceTo(real_node_poses[j]) <
182 i, j, real_node_poses, graph, inf_matrix);
187 if (add_extra_tightening_edge)
191 0, N_VERTEX / 2, real_node_poses, graph, inf_matrix);
195 typename my_graph_t::edge_t& ed =
206 const my_graph_t graph_GT = graph;
208 cout <<
"graph nodes: " << graph_GT.nodeCount() << endl;
209 cout <<
"graph edges: " << graph_GT.edgeCount() << endl;
214 itEdge != graph.edges.end(); ++itEdge)
216 const typename my_graph_t::edge_t::type_value delta_noise(
225 itEdge->second.getPoseMean() +=
226 typename my_graph_t::edge_t::type_value(delta_noise);
231 itNode != graph.nodes.end(); ++itNode)
232 if (itNode->first != graph.root)
233 itNode->second.getPoseMean() +=
234 typename my_graph_t::edge_t::type_value(
250 const my_graph_t graph_initial = graph;
260 params[
"max_iterations"] = 500;
261 params[
"scale_hessian"] = 0.1;
274 cout <<
"Global graph RMS error / edge = " 275 << std::sqrt(graph.getGlobalSquareError(
false) / graph.edgeCount())
277 cout <<
"Global graph RMS error / edge = " 278 << std::sqrt(graph.getGlobalSquareError(
true) / graph.edgeCount())
279 <<
" (ignoring information matrices)." << endl;
286 params, &my_levmarq_feedback<my_graph_t>);
288 cout <<
"Global graph RMS error / edge = " 289 << std::sqrt(graph.getGlobalSquareError(
false) / graph.edgeCount())
291 cout <<
"Global graph RMS error / edge = " 292 << std::sqrt(graph.getGlobalSquareError(
true) / graph.edgeCount())
293 <<
" (ignoring information matrices)." << endl;
303 graph_render_params1[
"show_edges"] = 1;
304 graph_render_params1[
"edge_width"] = 1;
305 graph_render_params1[
"nodes_corner_scale"] = 1;
308 graph, graph_render_params1);
312 graph_render_params2[
"show_ground_grid"] = 0;
313 graph_render_params2[
"show_edges"] = 0;
314 graph_render_params2[
"show_node_corners"] = 0;
315 graph_render_params2[
"nodes_point_size"] = 7;
319 graph_initial, graph_render_params2);
321 graph_render_params2[
"nodes_point_size"] = 5;
324 graph, graph_render_params2);
328 graph_render_params3[
"show_ground_grid"] = 0;
329 graph_render_params3[
"show_ID_labels"] = 1;
330 graph_render_params3[
"show_edges"] = 1;
331 graph_render_params3[
"edge_width"] = 3;
332 graph_render_params3[
"nodes_corner_scale"] = 2;
335 graph_GT, graph_render_params3);
338 graph_initial, graph_render_params3);
341 5, 5,
"Ground truth: Big corners & thick edges",
TColorf(0, 0, 0),
345 5, 5 + 15,
"Initial graph: Gray thick points.",
TColorf(0, 0, 0),
349 5, 5 + 30,
"Final graph: Small corners & thin edges",
354 5, 5,
"Ground truth: Big corners & thick edges",
TColorf(0, 0, 0),
358 5, 5 + 15,
"Initial graph: Small corners & thin edges",
364 scene->insert(gl_graph1);
365 scene->insert(gl_graph3);
366 scene->insert(gl_graph2);
367 scene->insert(gl_graph5);
368 win.unlockAccess3DScene();
374 scene->insert(gl_graph3);
375 scene->insert(gl_graph4);
376 win2.unlockAccess3DScene();
386 cout <<
"Close any window to end...\n";
387 while (
win.isOpen() && win2.isOpen() && win_err.isOpen() &&
390 std::this_thread::sleep_for(10ms);
401 cout <<
"Select the type of graph to optimize:\n" 402 "1. CNetworkOfPoses2D \n" 403 "2. CNetworkOfPoses2DInf \n" 404 "3. CNetworkOfPoses3D \n" 405 "4. CNetworkOfPoses3DInf \n";
412 std::getline(cin, l);
417 bool add_extra_tightening_edge;
418 cout <<
"Add an extra, incompatible tightening edge? [y/N] ";
421 std::getline(cin, l);
423 add_extra_tightening_edge = l[0] ==
'Y' || l[0] ==
'y';
431 demo.
run(add_extra_tightening_edge);
437 demo.
run(add_extra_tightening_edge);
443 demo.
run(add_extra_tightening_edge);
449 demo.
run(add_extra_tightening_edge);
454 std::this_thread::sleep_for(20ms);
459 cout <<
"MRPT exception caught: " << e.what() << endl;
464 printf(
"Another exception!!");
A namespace of pseudo-random numbers generators of diferent distributions.
Generic struct template Auxiliary class to add a new edge to the graph.
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(), typename graphslam_traits< GRAPH_T >::TFunctorFeedback functor_feedback=typename graphslam_traits< GRAPH_T >::TFunctorFeedback())
Optimize a graph of pose constraints using the Sparse Pose Adjustment (SPA) sparse representation and...
void addEdge(TNodeID from, TNodeID to, const mrpt::aligned_std_map< TNodeID, CPose2D > &real_poses, CNetworkOfPoses2D &graph_links)
Create a GUI window and display plots with MATLAB-like interfaces and commands.
double DEG2RAD(const double x)
Degrees to radians.
Abstract graph and tree data structures, plus generic graph algorithms.
void randomize(const uint32_t seed)
Initialize the PRNG from the given random seed.
T square(const T x)
Inline function for the square of a number.
SLAM methods related to graphs of pose constraints.
const double STD_NOISE_NODE_XYZ
This base provides a set of functions for maths stuff.
mrpt::gui::CDisplayWindow3D::Ptr win
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
const double STD4EDGES_COV_MATRIX
const double STD_NOISE_EDGE_ANG
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void run(bool add_extra_tightening_edge)
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
A RGB color - floats in the range [0,1].
Output information for mrpt::graphslam::optimize_graph_spa_levmarq()
The namespace for 3D scene representation and rendering.
bool kbhit() noexcept
An OS-independent version of kbhit, which returns true if a key has been pushed.
CSetOfObjects::Ptr graph_visualize(const GRAPH_T &g, const mrpt::system::TParametersDouble &extra_params=mrpt::system::TParametersDouble())
Returns an opengl objects representation of an arbitrary graph, as a network of 3D pose frames...
uint64_t TNodeID
A generic numeric type for unique IDs of nodes or entities.
std::string trim(const std::string &str)
Removes leading and trailing spaces.
const double STD_NOISE_NODE_ANG
Classes for creating GUI windows for 2D and 3D visualization.
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
GLenum const GLfloat * params
const double STD_NOISE_EDGE_XYZ
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.
const double ERROR_IN_INCOMPATIBLE_EDGE
vector< double > log_sq_err_evolution