19 template <
class GRAPH_T>
22 m_search_disk_color(142, 142, 56),
23 m_laser_scans_color(0, 20, 255)
45 template <
class GRAPH_T>
55 bool registered_new_node =
false;
57 if (this->m_last_total_num_nodes < this->m_graph->nodeCount())
59 registered_new_node =
true;
60 this->m_last_total_num_nodes = this->m_graph->nodeCount();
71 m_is_using_3DScan =
false;
81 m_last_laser_scan3D->
load();
84 this->convert3DTo2DRangeScan(
86 &m_fake_laser_scan2D);
88 m_is_using_3DScan =
true;
93 if (registered_new_node)
95 if (m_last_laser_scan2D)
97 this->m_nodes_to_laser_scans2D[this->m_graph->nodeCount() - 1] =
100 "Added laser scans of nodeID: %u",
101 (
unsigned)(this->m_graph->nodeCount() - 1)));
103 if (m_last_laser_scan3D)
105 m_nodes_to_laser_scans3D[this->m_graph->nodeCount() - 1] =
108 "Added laser scans of nodeID: %u",
109 (
unsigned)(this->m_graph->nodeCount() - 1)));
116 m_last_laser_scan2D =
118 if (registered_new_node && m_last_laser_scan2D)
120 this->m_nodes_to_laser_scans2D[this->m_graph->nodeCount() - 1] =
126 if (registered_new_node)
129 std::set<mrpt::graphs::TNodeID> nodes_to_check_ICP;
130 this->getNearbyNodesOf(
131 &nodes_to_check_ICP, this->m_graph->nodeCount() - 1,
134 "Found * %lu * nodes close to nodeID %lu",
135 nodes_to_check_ICP.size(), this->m_graph->nodeCount() - 1);
138 this->m_just_inserted_lc =
false;
139 registered_new_node =
false;
141 if (m_is_using_3DScan)
143 checkRegistrationCondition3D(nodes_to_check_ICP);
147 checkRegistrationCondition2D(nodes_to_check_ICP);
155 template <
class GRAPH_T>
157 const std::set<mrpt::graphs::TNodeID>& nodes_set)
160 using namespace mrpt;
166 typename nodes_to_scans2D_t::const_iterator search;
169 search = this->m_nodes_to_laser_scans2D.find(curr_nodeID);
170 if (search != this->m_nodes_to_laser_scans2D.end())
172 curr_laser_scan = search->second;
187 search = this->m_nodes_to_laser_scans2D.find(node_it);
188 if (search != this->m_nodes_to_laser_scans2D.end())
190 prev_laser_scan = search->second;
193 pose_t initial_pose = this->m_graph->nodes[curr_nodeID] -
194 this->m_graph->nodes[node_it];
196 this->m_time_logger.enter(
"CICPCriteriaERD::getICPEdge");
198 *prev_laser_scan, *curr_laser_scan, &rel_edge,
199 &initial_pose, &icp_info);
200 this->m_time_logger.leave(
"CICPCriteriaERD::getICPEdge");
204 ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 207 "ICP constraint between NON-successive nodes: " 208 << node_it <<
" => " << curr_nodeID << std::endl
210 <<
"\tgoodness = " << icp_info.
goodness);
212 "ICP_goodness_thresh: " <<
params.ICP_goodness_thresh);
214 "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" 220 this->registerNewEdge(node_it, curr_nodeID, rel_edge);
221 m_edge_types_to_nums[
"ICP2D"]++;
223 if (
absDiff(curr_nodeID, node_it) >
224 params.LC_min_nodeid_diff)
226 m_edge_types_to_nums[
"LC"]++;
227 this->m_just_inserted_lc =
true;
236 template <
class GRAPH_T>
238 const std::set<mrpt::graphs::TNodeID>& nodes_set)
247 std::map<mrpt::graphs::TNodeID, mrpt::obs::CObservation3DRangeScan::Ptr>::
248 const_iterator search;
250 search = m_nodes_to_laser_scans3D.find(curr_nodeID);
251 if (search != m_nodes_to_laser_scans3D.end())
253 curr_laser_scan = search->second;
268 search = m_nodes_to_laser_scans3D.find(node_it);
269 if (search != m_nodes_to_laser_scans3D.end())
271 prev_laser_scan = search->second;
274 this->m_time_logger.enter(
"CICPCriteriaERD::getICPEdge");
276 *prev_laser_scan, *curr_laser_scan, &rel_edge,
nullptr,
278 this->m_time_logger.leave(
"CICPCriteriaERD::getICPEdge");
283 this->registerNewEdge(node_it, curr_nodeID, rel_edge);
284 m_edge_types_to_nums[
"ICP3D"]++;
286 if (
absDiff(curr_nodeID, node_it) >
287 params.LC_min_nodeid_diff)
289 m_edge_types_to_nums[
"LC"]++;
290 this->m_just_inserted_lc =
true;
300 template <
class GRAPH_T>
305 parent_t::registerNewEdge(from, to, rel_edge);
307 this->m_graph->insertEdge(from, to, rel_edge);
310 template <
class GRAPH_T>
312 std::set<mrpt::graphs::TNodeID>* nodes_set,
321 nodeID < this->m_graph->nodeCount() - 1; ++nodeID)
323 double curr_distance = this->m_graph->nodes[nodeID].distanceTo(
324 this->m_graph->nodes[cur_nodeID]);
327 nodes_set->insert(nodeID);
333 this->m_graph->getAllNodes(*nodes_set);
339 template <
class GRAPH_T>
341 const std::map<std::string, bool>& events_occurred)
344 parent_t::notifyOfWindowEvents(events_occurred);
347 if (events_occurred.find(
params.keystroke_laser_scans)->second)
349 this->toggleLaserScansVisualization();
355 template <
class GRAPH_T>
359 ASSERTDEBMSG_(this->m_win,
"No CDisplayWindow3D* was provided");
360 ASSERTDEBMSG_(this->m_win_manager,
"No CWindowManager* was provided");
369 if (
params.visualize_laser_scans)
372 obj->setVisibility(!obj->isVisible());
376 dumpVisibilityErrorMsg(
"visualize_laser_scans");
379 this->m_win->unlockAccess3DScene();
380 this->m_win->forceRepaint();
385 template <
class GRAPH_T>
387 std::map<std::string, int>* edge_types_to_num)
const 391 *edge_types_to_num = m_edge_types_to_nums;
396 template <
class GRAPH_T>
402 this->m_time_logger.enter(
"CICPCriteriaERD::Visuals");
403 parent_t::initializeVisuals();
406 params.has_read_config,
"Configuration parameters aren't loaded yet");
408 this->m_win_observer->registerKeystroke(
409 params.keystroke_laser_scans,
"Toggle LaserScans Visualization");
412 if (
params.ICP_max_distance > 0)
418 obj->setPose(initial_pose);
419 obj->setName(
"ICP_max_distance");
420 obj->setColor_u8(m_search_disk_color);
422 params.ICP_max_distance,
params.ICP_max_distance - 0.1);
425 this->m_win->unlockAccess3DScene();
426 this->m_win->forceRepaint();
430 if (
params.visualize_laser_scans)
436 laser_scan_viz->enablePoints(
true);
437 laser_scan_viz->enableLine(
true);
438 laser_scan_viz->enableSurface(
true);
439 laser_scan_viz->setSurfaceColor(
440 m_laser_scans_color.R, m_laser_scans_color.G, m_laser_scans_color.B,
441 m_laser_scans_color.A);
443 laser_scan_viz->setName(
"laser_scan_viz");
445 scene->insert(laser_scan_viz);
446 this->m_win->unlockAccess3DScene();
447 this->m_win->forceRepaint();
451 if (this->m_win && this->m_win_manager &&
params.ICP_max_distance > 0)
453 this->m_win_manager->assignTextMessageParameters(
454 &m_offset_y_search_disk, &m_text_index_search_disk);
456 this->m_win_manager->addTextMessage(
457 5, -m_offset_y_search_disk,
"ICP Edges search radius",
459 m_text_index_search_disk);
462 this->m_time_logger.leave(
"CICPCriteriaERD::Visuals");
465 template <
class GRAPH_T>
469 this->m_time_logger.enter(
"CICPCriteriaERD::Visuals");
473 parent_t::updateVisuals();
476 if (this->m_win &&
params.ICP_max_distance > 0)
483 disk_obj->setPose(this->m_graph->nodes[this->m_graph->nodeCount() - 1]);
485 this->m_win->unlockAccess3DScene();
486 this->m_win->forceRepaint();
490 if (this->m_win &&
params.visualize_laser_scans &&
491 (m_last_laser_scan2D || m_fake_laser_scan2D))
500 if (m_fake_laser_scan2D)
502 laser_scan_viz->setScan(*m_fake_laser_scan2D);
506 laser_scan_viz->setScan(*m_last_laser_scan2D);
510 auto search = this->m_graph->nodes.find(this->m_graph->nodeCount() - 1);
511 if (search != this->m_graph->nodes.end())
513 laser_scan_viz->setPose(
514 this->m_graph->nodes[this->m_graph->nodeCount() - 1]);
517 laser_scan_viz->setPose(
CPose3D(
518 laser_scan_viz->getPoseX(), laser_scan_viz->getPoseY(), -0.15,
519 DEG2RAD(laser_scan_viz->getPoseYaw()),
520 DEG2RAD(laser_scan_viz->getPosePitch()),
521 DEG2RAD(laser_scan_viz->getPoseRoll())));
524 this->m_win->unlockAccess3DScene();
525 this->m_win->forceRepaint();
528 this->m_time_logger.leave(
"CICPCriteriaERD::Visuals");
532 template <
class GRAPH_T>
534 std::string viz_flag,
int sleep_time )
537 using namespace mrpt;
540 "Cannot toggle visibility of specified object.\n " 541 "Make sure that the corresponding visualization flag ( %s " 542 ") is set to true in the .ini file.\n",
544 std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
549 template <
class GRAPH_T>
553 parent_t::loadParams(source_fname);
555 params.loadFromConfigFileName(
556 source_fname,
"EdgeRegistrationDeciderParameters");
561 int min_verbosity_level = source.
read_int(
562 "EdgeRegistrationDeciderParameters",
"class_verbosity", 1,
false);
567 template <
class GRAPH_T>
571 parent_t::printParams();
577 template <
class GRAPH_T>
579 std::string* report_str)
const 584 const std::string report_sep(2,
'\n');
585 const std::string header_sep(80,
'#');
588 stringstream class_props_ss;
589 class_props_ss <<
"ICP Goodness-based Registration Procedure Summary: " 591 class_props_ss << header_sep << std::endl;
594 const std::string time_res = this->m_time_logger.getStatsAsText();
595 const std::string output_res = this->getLogAsString();
599 parent_t::getDescriptiveReport(report_str);
601 *report_str += class_props_ss.str();
602 *report_str += report_sep;
604 *report_str += time_res;
605 *report_str += report_sep;
607 *report_str += output_res;
608 *report_str += report_sep;
616 template <
class GRAPH_T>
618 : decider(d), keystroke_laser_scans(
"l"), has_read_config(false)
622 template <
class GRAPH_T>
625 template <
class GRAPH_T>
627 std::ostream&
out)
const 631 out <<
"------------------[ Goodness-based ICP Edge Registration " 632 "]------------------\n";
634 "ICP goodness threshold = %.2f%% \n",
635 ICP_goodness_thresh * 100);
637 "ICP max radius for edge search = %.2f\n", ICP_max_distance);
639 "Min. node difference for LC = %lu\n", LC_min_nodeid_diff);
641 "Visualize laser scans = %d\n", visualize_laser_scans);
643 "3DScans Image Directory = %s\n",
644 scans_img_external_dir.c_str());
648 template <
class GRAPH_T>
654 LC_min_nodeid_diff = source.
read_int(
655 "GeneralConfiguration",
"LC_min_nodeid_diff", 30,
false);
657 source.
read_double(section,
"ICP_max_distance", 10,
false);
658 ICP_goodness_thresh =
659 source.
read_double(section,
"ICP_goodness_thresh", 0.75,
false);
660 visualize_laser_scans = source.
read_bool(
661 "VisualizationParameters",
"visualize_laser_scans",
true,
false);
663 section,
"scan_images_external_directory",
"./",
false);
665 has_read_config =
true;
void checkRegistrationCondition2D(const std::set< mrpt::graphs::TNodeID > &nodes_set)
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
typename GRAPH_T::constraint_t::type_value pose_t
type of underlying poses (2D/3D).
ICP-based Edge Registration.
VerbosityLevel
Enumeration of available verbosity levels.
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
void dumpToTextStream(std::ostream &out) const override
This method should clearly display all the contents of the structure in textual form, sending it to a std::ostream.
std::string std::string format(std::string_view fmt, ARGS &&... args)
app setMinLoggingLevel(mrpt::system::LVL_ERROR)
static Ptr Create(Args &&... args)
void dumpVisibilityErrorMsg(std::string viz_flag, int sleep_time=500)
void loadParams(const std::string &source_fname) override
Load the necessary for the decider/optimizer configuration parameters.
This class allows loading and storing values and vectors of different types from ".ini" files easily.
A range or depth 3D scan measurement, as from a time-of-flight range camera or a structured-light dep...
mrpt::vision::TStereoCalibParams params
void updateVisuals() override
Update the relevant visual features in CDisplayWindow.
unsigned int nIterations
The number of executed iterations until convergence.
size_t m_last_total_num_nodes
Keep track of the total number of registered nodes since the last time class method was called...
void printParams() const override
Print the problem parameters - relevant to the decider/optimizer to the screen in a unified/compact w...
void notifyOfWindowEvents(const std::map< std::string, bool > &events_occurred) override
Get a list of the window events that happened since the last call.
void toggleLaserScansVisualization()
togle the LaserScans visualization on and off
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string §ion) override
This method load the options from a ".ini"-like file or memory-stored string list.
This class allows loading and storing values and vectors of different types from a configuration text...
This base provides a set of functions for maths stuff.
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
Use: MRPT_LOG_DEBUG_FMT("i=%u", i);
constexpr double DEG2RAD(const double x)
Degrees to radians.
A planar disk in the XY plane.
void checkRegistrationCondition3D(const std::set< mrpt::graphs::TNodeID > &nodes_set)
This namespace contains representation of robot actions and observations.
This object renders a 2D laser scan by means of three elements: the points, the line along end-points...
#define IS_CLASS(obj, class_name)
True if the given reference to object (derived from mrpt::rtti::CObject) is of the given class...
double goodness
A goodness measure for the alignment, it is a [0,1] range indicator of percentage of correspondences...
double read_double(const std::string §ion, const std::string &name, double defaultValue, bool failIfNotFound=false) const
void getEdgesStats(std::map< std::string, int > *edge_types_to_num) const override
Fill the given map with the type of registered edges as well as the corresponding number of registrat...
virtual void initializeLoggers(const std::string &name)
Initialize the COutputLogger, CTimeLogger instances given the name of the decider/optimizer at hand...
#define MRPT_LOG_DEBUG_STREAM(__CONTENTS)
Use: MRPT_LOG_DEBUG_STREAM("Var=" << value << " foo=" << foo_var);
void getDescriptiveReport(std::string *report_str) const override
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) override
Generic method for fetching the incremental action-observations (or observation-only) measurements...
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
std::map< std::string, int > m_edge_types_to_nums
#define ASSERTDEBMSG_(f, __ERROR_MSG)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
void registerNewEdge(const mrpt::graphs::TNodeID &from, const mrpt::graphs::TNodeID &to, const constraint_t &rel_edge) override
Register a new constraint/edge in the current graph.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
mrpt::vision::TStereoCalibResults out
void initializeVisuals() override
Initialize visual objects in CDisplayWindow (e.g.
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
An RGBA color - floats in the range [0,1].
The ICP algorithm return information.
The namespace for 3D scene representation and rendering.
uint64_t TNodeID
A generic numeric type for unique IDs of nodes or entities.
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...
T absDiff(const T &lhs, const T &rhs)
Absolute difference between two numbers.
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
void load() const override
Makes sure all images and other fields which may be externally stored are loaded in memory...
typename GRAPH_T::constraint_t constraint_t
Handy typedefs.