10 #ifndef CLEVMARQGSO_IMPL_H
11 #define CLEVMARQGSO_IMPL_H
18 template <
class GRAPH_T>
20 : m_first_time_call(false),
21 m_has_read_config(false),
22 m_autozoom_active(true),
23 m_last_total_num_of_nodes(5),
24 m_optimization_policy(FOP_USE_LC),
25 m_curr_used_consec_lcs(0),
26 m_curr_ignored_consec_lcs(0),
27 m_just_fully_optimized_graph(false),
28 m_min_nodes_for_optimization(3)
35 template <
class GRAPH_T>
44 template <
class GRAPH_T>
53 if (this->m_graph->nodeCount() > m_last_total_num_of_nodes)
55 m_last_total_num_of_nodes = this->m_graph->nodeCount();
56 registered_new_node =
true;
58 if (m_first_time_call)
60 opt_params.last_pair_nodes_to_edge = this->m_graph->edges;
61 m_first_time_call =
true;
64 if (opt_params.optimization_on_second_thread)
67 m_thread_optimize.join();
74 bool is_full_update = this->checkForFullOptimization();
75 this->_optimizeGraph(is_full_update);
83 template <
class GRAPH_T>
88 parent::initializeVisuals();
90 this->initGraphVisualization();
91 this->initOptDistanceVisualization();
96 template <
class GRAPH_T>
100 parent::updateVisuals();
102 if (opt_params.optimization_distance > 0)
104 this->updateOptDistanceVisualization();
107 this->updateGraphVisualization();
112 template <
class GRAPH_T>
114 const std::map<std::string, bool>& events_occurred)
118 parent::notifyOfWindowEvents(events_occurred);
123 if (opt_params.optimization_distance > 0)
125 if (events_occurred.find(opt_params.keystroke_optimization_distance)
128 this->toggleOptDistanceVisualization();
131 if (events_occurred.find(opt_params.keystroke_optimize_graph)->second)
133 this->_optimizeGraph(
true);
138 if (events_occurred.find(viz_params.keystroke_graph_toggle)->second)
140 this->toggleGraphVisualization();
144 if (events_occurred.find(
"mouse_clicked")->second)
147 m_autozoom_active =
false;
151 if (events_occurred.find(viz_params.keystroke_graph_autofit)->second)
154 this->fitGraphInView();
160 template <
class GRAPH_T>
164 ASSERTDEBMSG_(this->m_win_manager,
"No CWindowManager* is given");
166 if (viz_params.visualize_optimized_graph)
168 this->m_win_observer->registerKeystroke(
169 viz_params.keystroke_graph_toggle,
"Toggle Graph visualization");
170 this->m_win_observer->registerKeystroke(
171 viz_params.keystroke_graph_autofit,
"Fit Graph in view");
173 this->m_win_manager->assignTextMessageParameters(
174 &viz_params.offset_y_graph,
175 &viz_params.text_index_graph);
180 template <
class GRAPH_T>
184 ASSERTDEBMSG_(this->m_win_manager,
"No CWindowManager* is given");
196 bool prev_visibility =
true;
199 prev_visibility = prev_object->isVisible();
201 scene->removeObject(prev_object);
206 this->m_graph->getAs3DObject(graph_obj, viz_params.cfg);
208 graph_obj->setName(
"optimized_graph");
209 graph_obj->setVisibility(prev_visibility);
210 scene->insert(graph_obj);
211 this->m_win->unlockAccess3DScene();
213 this->m_win_manager->addTextMessage(
214 5, -viz_params.offset_y_graph,
216 "Optimized Graph: #nodes %d",
217 static_cast<int>(this->m_graph->nodeCount())),
219 viz_params.text_index_graph);
221 this->m_win->forceRepaint();
223 if (m_autozoom_active)
225 this->fitGraphInView();
231 template <
class GRAPH_T>
240 graph_obj->setVisibility(!graph_obj->isVisible());
242 this->m_win->unlockAccess3DScene();
243 this->m_win->forceRepaint();
248 template <
class GRAPH_T>
256 "\nVisualization of data was requested but no CDisplayWindow3D pointer "
263 std::dynamic_pointer_cast<CSetOfObjects>(
obj);
264 this->m_win->unlockAccess3DScene();
265 this->m_win->forceRepaint();
272 float x_min, x_max, y_min, y_max;
274 const float z_min = obj_grid->getPlaneZcoord();
275 this->m_win->setCameraPointingToPoint(
276 0.5 * (x_min + x_max), 0.5 * (y_min + y_max), z_min);
277 this->m_win->setCameraZoom(
278 2.0f * std::max(10.0f, std::max(x_max - x_min, y_max - y_min)));
280 this->m_win->setCameraAzimuthDeg(60);
281 this->m_win->setCameraElevationDeg(75);
282 this->m_win->setCameraProjective(
true);
287 template <
class GRAPH_T>
293 if (opt_params.optimization_distance > 0)
295 this->m_win_observer->registerKeystroke(
296 opt_params.keystroke_optimization_distance,
297 "Toggle optimization distance on/off");
299 this->m_win_observer->registerKeystroke(
300 opt_params.keystroke_optimize_graph,
301 "Manually trigger a full graph optimization");
307 obj->setPose(initial_pose);
308 obj->setName(
"optimization_distance_obj");
312 this->m_win->unlockAccess3DScene();
313 this->m_win->forceRepaint();
316 this->m_win_manager->assignTextMessageParameters(
317 &opt_params.offset_y_optimization_distance,
318 &opt_params.text_index_optimization_distance);
320 this->m_win_manager->addTextMessage(
321 5, -opt_params.offset_y_optimization_distance,
322 format(
"Radius for graph optimization"),
324 opt_params.text_index_optimization_distance);
328 template <
class GRAPH_T>
337 opt_params.optimization_distance,
338 opt_params.optimization_distance - 0.1);
339 obj->setColor_u8(opt_params.optimization_distance_color);
343 template <
class GRAPH_T>
351 obj->setRadius(opt_params.optimization_distance);
353 opt_params.optimization_distance_color.R,
354 opt_params.optimization_distance_color.G,
355 opt_params.optimization_distance_color.B,
361 template <
class GRAPH_T>
365 ASSERTDEBMSG_(this->m_win_manager,
"No CWindowManager* is given");
372 obj->setPose(this->m_graph->nodes.rbegin()->second);
374 this->m_win->unlockAccess3DScene();
375 this->m_win->forceRepaint();
380 template <
class GRAPH_T>
389 obj->setVisibility(!
obj->isVisible());
391 this->m_win->unlockAccess3DScene();
392 this->m_win->forceRepaint();
397 template <
class GRAPH_T>
404 "optimizeGraph:: ThreadID:" << endl
405 <<
"\t" << std::this_thread::get_id()
408 <<
"Trying to grab lock... ");
410 std::lock_guard<std::mutex> graph_lock(*this->m_graph_section);
411 this->_optimizeGraph();
418 template <
class GRAPH_T>
422 this->m_time_logger.enter(
"CLevMarqGSO::_optimizeGraph");
425 if (m_min_nodes_for_optimization > this->m_graph->nodes.size())
431 optimization_timer.
Tic();
434 std::set<mrpt::graphs::TNodeID>* nodes_to_optimize;
443 nodes_to_optimize = NULL;
447 nodes_to_optimize =
new std::set<mrpt::graphs::TNodeID>;
453 this->getNearbyNodesOf(
454 nodes_to_optimize, this->m_graph->nodeCount() - 1,
455 opt_params.optimization_distance);
456 nodes_to_optimize->insert(this->m_graph->nodeCount() - 1);
463 *(this->m_graph), levmarq_info, nodes_to_optimize, opt_params.cfg,
468 m_just_fully_optimized_graph =
true;
472 m_just_fully_optimized_graph =
false;
475 double elapsed_time = optimization_timer.
Tac();
481 delete nodes_to_optimize;
482 nodes_to_optimize =
nullptr;
484 this->m_time_logger.leave(
"CLevMarqGSO::_optimizeGraph");
489 template <
class GRAPH_T>
494 bool is_loop_closure =
false;
495 auto curr_pair_nodes_to_edge = this->m_graph->edges;
505 curr_pair_nodes_to_edge.begin();
506 it != curr_pair_nodes_to_edge.end(); ++it)
508 search = opt_params.last_pair_nodes_to_edge.find(it->first);
510 if (search == opt_params.last_pair_nodes_to_edge.end())
512 curr_pair = it->first;
515 static_cast<int>(curr_pair.first) -
516 static_cast<int>(curr_pair.second)) >
517 opt_params.LC_min_nodeid_diff)
521 is_loop_closure =
true;
528 opt_params.last_pair_nodes_to_edge = curr_pair_nodes_to_edge;
529 return is_loop_closure;
534 template <
class GRAPH_T>
537 bool is_full_update =
false;
539 if (opt_params.optimization_distance == -1)
544 bool added_lc = this->checkForLoopClosures();
549 if (m_curr_used_consec_lcs != 0 || m_curr_ignored_consec_lcs != 0)
554 m_curr_used_consec_lcs = 0;
555 m_curr_ignored_consec_lcs = 0;
556 m_optimization_policy = FOP_USE_LC;
558 return is_full_update;
563 bool use_limit_reached =
564 m_curr_used_consec_lcs == m_max_used_consec_lcs;
566 bool ignore_limit_reached =
567 m_curr_ignored_consec_lcs == m_max_ignored_consec_lcs;
570 if (ignore_limit_reached || use_limit_reached)
572 m_curr_ignored_consec_lcs = 0;
573 m_curr_used_consec_lcs = 0;
576 if (ignore_limit_reached)
578 m_optimization_policy = FOP_USE_LC;
580 if (use_limit_reached)
582 m_optimization_policy = FOP_IGNORE_LC;
587 if (m_optimization_policy == FOP_USE_LC)
589 m_curr_used_consec_lcs += 1;
593 m_curr_ignored_consec_lcs += 1;
599 if (m_optimization_policy == FOP_IGNORE_LC)
601 is_full_update =
false;
603 "*PARTIAL* graph optimization.. ignoring new loop closure");
607 is_full_update =
true;
610 return is_full_update;
614 template <
class GRAPH_T>
617 return m_just_fully_optimized_graph;
620 template <
class GRAPH_T>
622 const GRAPH_T& graph,
const size_t iter,
const size_t max_iter,
623 const double cur_sq_error)
627 template <
class GRAPH_T>
629 std::set<mrpt::graphs::TNodeID>* nodes_set,
638 nodeID < this->m_graph->nodeCount() - 1; ++nodeID)
640 double curr_distance = this->m_graph->nodes[nodeID].distanceTo(
641 this->m_graph->nodes[cur_nodeID]);
644 nodes_set->insert(nodeID);
650 this->m_graph->getAllNodes(*nodes_set);
656 template <
class GRAPH_T>
659 parent::printParams();
661 opt_params.dumpToConsole();
662 viz_params.dumpToConsole();
664 template <
class GRAPH_T>
668 parent::loadParams(source_fname);
670 opt_params.loadFromConfigFileName(source_fname,
"OptimizerParameters");
671 viz_params.loadFromConfigFileName(source_fname,
"VisualizationParameters");
676 m_max_used_consec_lcs =
source.read_int(
677 "OptimizerParameters",
"max_used_consecutive_loop_closures", 2,
false);
679 m_max_ignored_consec_lcs =
source.read_int(
680 "OptimizerParameters",
"max_ignored_consecutive_loop_closures", 15,
685 int min_verbosity_level =
686 source.read_int(
"OptimizerParameters",
"class_verbosity", 1,
false);
690 m_has_read_config =
true;
695 template <
class GRAPH_T>
705 stringstream class_props_ss;
706 class_props_ss <<
"Levenberg Marquardt Optimization Summary: " << std::endl;
707 class_props_ss << header_sep << std::endl;
710 const std::string time_res = this->m_time_logger.getStatsAsText();
711 const std::string output_res = this->getLogAsString();
715 parent::getDescriptiveReport(report_str);
717 *report_str += class_props_ss.str();
718 *report_str += report_sep;
720 *report_str += time_res;
721 *report_str += report_sep;
723 *report_str += output_res;
724 *report_str += report_sep;
731 template <
class GRAPH_T>
733 : optimization_distance_color(0, 201, 87),
734 keystroke_optimization_distance(
"u"),
735 keystroke_optimize_graph(
"w")
738 template <
class GRAPH_T>
742 template <
class GRAPH_T>
744 std::ostream& out)
const
747 out <<
"-----------[ Levenberg-Marquardt Optimization ] -------\n";
748 out <<
"Optimization on second thread = "
749 << (optimization_on_second_thread ?
"TRUE" :
"FALSE") << std::endl;
750 out <<
"Optimize nodes in distance = " << optimization_distance <<
"\n";
751 out <<
"Min. node difference for LC = " << LC_min_nodeid_diff <<
"\n";
752 out << cfg.getAsString() << std::endl;
755 template <
class GRAPH_T>
760 optimization_on_second_thread =
source.read_bool(
761 section,
"optimization_on_second_thread",
false,
false);
762 LC_min_nodeid_diff =
source.read_int(
763 "GeneralConfiguration",
"LC_min_nodeid_diff", 30,
false);
764 optimization_distance =
765 source.read_double(section,
"optimization_distance", 5,
false);
768 optimization_distance == 1 || optimization_distance > 0,
770 "Invalid value for optimization distance: %.2f",
771 optimization_distance));
774 cfg[
"verbose"] =
source.read_bool(section,
"verbose", 0,
false);
775 cfg[
"profiler"] =
source.read_bool(section,
"profiler", 0,
false);
776 cfg[
"max_iterations"] =
777 source.read_double(section,
"max_iterations", 100,
false);
778 cfg[
"scale_hessian"] =
779 source.read_double(
"Optimization",
"scale_hessian", 0.2,
false);
780 cfg[
"tau"] =
source.read_double(section,
"tau", 1e-3,
false);
787 template <
class GRAPH_T>
789 : keystroke_graph_toggle(
"s"), keystroke_graph_autofit(
"a")
792 template <
class GRAPH_T>
796 template <
class GRAPH_T>
798 std::ostream& out)
const
803 "-----------[ Graph Visualization Parameters ]-----------\n");
805 "Visualize optimized graph = %s\n",
806 visualize_optimized_graph ?
"TRUE" :
"FALSE");
810 std::cout << std::endl;
814 template <
class GRAPH_T>
820 visualize_optimized_graph =
821 source.read_bool(section,
"visualize_optimized_graph", 1,
false);
823 cfg[
"show_ID_labels"] =
824 source.read_bool(section,
"optimized_show_ID_labels", 0,
false);
825 cfg[
"show_ground_grid"] =
826 source.read_double(section,
"optimized_show_ground_grid", 1,
false);
828 source.read_bool(section,
"optimized_show_edges", 1,
false);
830 source.read_int(section,
"optimized_edge_color", 4286611456,
false);
832 source.read_double(section,
"optimized_edge_width", 1.5,
false);
833 cfg[
"show_node_corners"] =
834 source.read_bool(section,
"optimized_show_node_corners", 1,
false);
835 cfg[
"show_edge_rel_poses"] =
836 source.read_bool(section,
"optimized_show_edge_rel_poses", 1,
false);
837 cfg[
"edge_rel_poses_color"] =
source.read_int(
838 section,
"optimized_edge_rel_poses_color", 1090486272,
false);
839 cfg[
"nodes_edges_corner_scale"] =
source.read_double(
840 section,
"optimized_nodes_edges_corner_scale", 0.4,
false);
841 cfg[
"nodes_corner_scale"] =
842 source.read_double(section,
"optimized_nodes_corner_scale", 0.7,
false);
843 cfg[
"nodes_point_size"] =
844 source.read_int(section,
"optimized_nodes_point_size", 5,
false);
845 cfg[
"nodes_point_color"] =
source.read_int(
846 section,
"optimized_nodes_point_color", 10526880,
false);
This class allows loading and storing values and vectors of different types from a configuration text...
This class allows loading and storing values and vectors of different types from "....
virtual void initializeLoggers(const std::string &name)
Initialize the COutputLogger, CTimeLogger instances given the name of the decider/optimizer at hand.
Levenberg-Marquardt non-linear graph slam optimization scheme.
bool checkForLoopClosures()
Check if a loop closure edge was added in the graph.
void updateOptDistanceVisualization()
Update the position of the disk indicating the distance in which Levenberg-Marquardt graph optimizati...
void _optimizeGraph(bool is_full_update=false)
Optimize the given graph.
void fitGraphInView()
Set the camera parameters of the CDisplayWindow3D so that the whole graph is viewed in the window.
void updateGraphVisualization()
Called internally for updating the visualization scene for the graph building procedure.
void initGraphVisualization()
Initialize objects relateed to the Graph Visualization.
void toggleGraphVisualization()
Toggle the graph visualization on and off.
void updateVisuals()
Update the relevant visual features in CDisplayWindow.
void getDescriptiveReport(std::string *report_str) const
Fill the provided string with a detailed report of the decider/optimizer state.
bool updateState(mrpt::obs::CActionCollection::Ptr action, mrpt::obs::CSensoryFrame::Ptr observations, mrpt::obs::CObservation::Ptr observation)
Generic method for fetching the incremental action/observation readings from the calling function.
void loadParams(const std::string &source_fname)
Load the necessary for the decider/optimizer configuration parameters.
static void levMarqFeedback(const GRAPH_T &graph, const size_t iter, const size_t max_iter, const double cur_sq_error)
Feedback of the Levenberg-Marquardt graph optimization procedure.
void optimizeGraph()
Wrapper around _optimizeGraph which first locks the section and then calls the _optimizeGraph method.
void notifyOfWindowEvents(const std::map< std::string, bool > &events_occurred)
Get a list of the window events that happened since the last call.
mrpt::opengl::CRenderizable::Ptr initOptDistanceVisualizationInternal(const mrpt::poses::CPose2D &p_unused)
Setup the corresponding Disk/Sphere instance.
void initializeVisuals()
Initialize visual objects in CDisplayWindow (e.g.
typename GRAPH_T::constraint_t::type_value pose_t
type of underlying poses (2D/3D)
bool checkForFullOptimization()
Decide whether to issue a full graph optimization.
void getNearbyNodesOf(std::set< mrpt::graphs::TNodeID > *nodes_set, const mrpt::graphs::TNodeID &cur_nodeID, double distance)
Get a list of the nodeIDs whose position is within a certain distance to the specified nodeID.
void printParams() const
Print the problem parameters - relevant to the decider/optimizer to the screen in a unified/compact w...
void toggleOptDistanceVisualization()
toggle the optimization distance object on and off
void initOptDistanceVisualization()
Initialize the Disk/Sphere used for visualizing the optimization distance.
bool justFullyOptimizedGraph() const
Used by the caller to query for possible full graph optimization on the latest optimizer run.
std::shared_ptr< CActionCollection > Ptr
std::shared_ptr< CObservation > Ptr
std::shared_ptr< CSensoryFrame > Ptr
std::shared_ptr< CDisk > Ptr
A grid of lines over the XY plane.
void getPlaneLimits(float &xmin, float &xmax, float &ymin, float &ymax) const
std::shared_ptr< CGridPlaneXY > Ptr
std::shared_ptr< COpenGLScene > Ptr
std::shared_ptr< CRenderizable > Ptr
std::shared_ptr< CSetOfObjects > Ptr
std::shared_ptr< CSphere > Ptr
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 high-performance stopwatch, with typical resolution of nanoseconds.
void Tic() noexcept
Starts the stopwatch.
double Tac() noexcept
Stops the stopwatch.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
const Scalar * const_iterator
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
#define ASSERTDEBMSG_(f, __ERROR_MSG)
GLsizei GLsizei GLuint * obj
GLenum GLsizei GLenum format
GLsizei const GLchar ** string
GLsizei GLsizei GLchar * source
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
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...
std::pair< TNodeID, TNodeID > TPairNodeIDs
A pair of node IDs.
uint64_t TNodeID
A generic numeric type for unique IDs of nodes or entities.
The namespace for 3D scene representation and rendering.
VerbosityLevel
Enumeration of available verbosity levels.
Output information for mrpt::graphslam::optimize_graph_spa_levmarq()
void dumpToTextStream(std::ostream &out) const
This method should clearly display all the contents of the structure in textual form,...
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string §ion)
This method load the options from a ".ini"-like file or memory-stored string list.
GraphVisualizationParams()
~GraphVisualizationParams()
void dumpToTextStream(std::ostream &out) const
This method should clearly display all the contents of the structure in textual form,...
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string §ion)
This method load the options from a ".ini"-like file or memory-stored string list.
A RGB color - floats in the range [0,1].
#define MRPT_LOG_DEBUG_STREAM(__CONTENTS)
Use: MRPT_LOG_DEBUG_STREAM("Var=" << value << " foo=" << foo_var);
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
#define MRPT_LOG_WARN_STREAM(__CONTENTS)