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>
56 bool registered_new_node =
false;
58 if (this->m_last_total_num_nodes < this->m_graph->nodeCount())
60 registered_new_node =
true;
61 this->m_last_total_num_nodes = this->m_graph->nodeCount();
72 m_is_using_3DScan =
false;
82 m_last_laser_scan3D->
load();
85 this->convert3DTo2DRangeScan(
87 &m_fake_laser_scan2D);
89 m_is_using_3DScan =
true;
94 if (registered_new_node)
96 if (m_last_laser_scan2D)
98 this->m_nodes_to_laser_scans2D[this->m_graph->nodeCount() - 1] =
101 "Added laser scans of nodeID: %u",
102 (
unsigned)(this->m_graph->nodeCount() - 1)));
104 if (m_last_laser_scan3D)
106 m_nodes_to_laser_scans3D[this->m_graph->nodeCount() - 1] =
109 "Added laser scans of nodeID: %u",
110 (
unsigned)(this->m_graph->nodeCount() - 1)));
117 m_last_laser_scan2D =
119 if (registered_new_node && m_last_laser_scan2D)
121 this->m_nodes_to_laser_scans2D[this->m_graph->nodeCount() - 1] =
127 if (registered_new_node)
130 std::set<mrpt::graphs::TNodeID> nodes_to_check_ICP;
131 this->getNearbyNodesOf(
132 &nodes_to_check_ICP, this->m_graph->nodeCount() - 1,
135 "Found * %lu * nodes close to nodeID %lu",
136 nodes_to_check_ICP.size(), this->m_graph->nodeCount() - 1);
139 this->m_just_inserted_lc =
false;
140 registered_new_node =
false;
142 if (m_is_using_3DScan)
144 checkRegistrationCondition3D(nodes_to_check_ICP);
148 checkRegistrationCondition2D(nodes_to_check_ICP);
156 template <
class GRAPH_T>
158 const std::set<mrpt::graphs::TNodeID>& nodes_set)
161 using namespace mrpt;
167 typename nodes_to_scans2D_t::const_iterator search;
170 search = this->m_nodes_to_laser_scans2D.find(curr_nodeID);
171 if (search != this->m_nodes_to_laser_scans2D.end())
173 curr_laser_scan = search->second;
188 search = this->m_nodes_to_laser_scans2D.find(node_it);
189 if (search != this->m_nodes_to_laser_scans2D.end())
191 prev_laser_scan = search->second;
194 pose_t initial_pose = this->m_graph->nodes[curr_nodeID] -
195 this->m_graph->nodes[node_it];
197 this->m_time_logger.enter(
"CICPCriteriaERD::getICPEdge");
199 *prev_laser_scan, *curr_laser_scan, &rel_edge,
200 &initial_pose, &icp_info);
201 this->m_time_logger.leave(
"CICPCriteriaERD::getICPEdge");
205 ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 208 "ICP constraint between NON-successive nodes: " 209 << node_it <<
" => " << curr_nodeID << std::endl
211 <<
"\tgoodness = " << icp_info.
goodness);
213 "ICP_goodness_thresh: " <<
params.ICP_goodness_thresh);
215 "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" 221 this->registerNewEdge(node_it, curr_nodeID, rel_edge);
222 m_edge_types_to_nums[
"ICP2D"]++;
224 if (
absDiff(curr_nodeID, node_it) >
225 params.LC_min_nodeid_diff)
227 m_edge_types_to_nums[
"LC"]++;
228 this->m_just_inserted_lc =
true;
237 template <
class GRAPH_T>
239 const std::set<mrpt::graphs::TNodeID>& nodes_set)
248 std::map<mrpt::graphs::TNodeID, mrpt::obs::CObservation3DRangeScan::Ptr>::
249 const_iterator search;
251 search = m_nodes_to_laser_scans3D.find(curr_nodeID);
252 if (search != m_nodes_to_laser_scans3D.end())
254 curr_laser_scan = search->second;
269 search = m_nodes_to_laser_scans3D.find(node_it);
270 if (search != m_nodes_to_laser_scans3D.end())
272 prev_laser_scan = search->second;
275 this->m_time_logger.enter(
"CICPCriteriaERD::getICPEdge");
277 *prev_laser_scan, *curr_laser_scan, &rel_edge,
nullptr,
279 this->m_time_logger.leave(
"CICPCriteriaERD::getICPEdge");
284 this->registerNewEdge(node_it, curr_nodeID, rel_edge);
285 m_edge_types_to_nums[
"ICP3D"]++;
287 if (
absDiff(curr_nodeID, node_it) >
288 params.LC_min_nodeid_diff)
290 m_edge_types_to_nums[
"LC"]++;
291 this->m_just_inserted_lc =
true;
301 template <
class GRAPH_T>
306 parent_t::registerNewEdge(from, to, rel_edge);
308 this->m_graph->insertEdge(from, to, rel_edge);
311 template <
class GRAPH_T>
313 std::set<mrpt::graphs::TNodeID>* nodes_set,
322 nodeID < this->m_graph->nodeCount() - 1; ++nodeID)
324 double curr_distance = this->m_graph->nodes[nodeID].distanceTo(
325 this->m_graph->nodes[cur_nodeID]);
328 nodes_set->insert(nodeID);
334 this->m_graph->getAllNodes(*nodes_set);
340 template <
class GRAPH_T>
342 const std::map<std::string, bool>& events_occurred)
345 parent_t::notifyOfWindowEvents(events_occurred);
348 if (events_occurred.find(
params.keystroke_laser_scans)->second)
350 this->toggleLaserScansVisualization();
356 template <
class GRAPH_T>
360 ASSERTDEBMSG_(this->m_win,
"No CDisplayWindow3D* was provided");
361 ASSERTDEBMSG_(this->m_win_manager,
"No CWindowManager* was provided");
370 if (
params.visualize_laser_scans)
373 obj->setVisibility(!
obj->isVisible());
377 dumpVisibilityErrorMsg(
"visualize_laser_scans");
380 this->m_win->unlockAccess3DScene();
381 this->m_win->forceRepaint();
386 template <
class GRAPH_T>
388 std::map<std::string, int>* edge_types_to_num)
const 392 *edge_types_to_num = m_edge_types_to_nums;
397 template <
class GRAPH_T>
403 this->m_time_logger.enter(
"CICPCriteriaERD::Visuals");
404 parent_t::initializeVisuals();
407 params.has_read_config,
"Configuration parameters aren't loaded yet");
409 this->m_win_observer->registerKeystroke(
410 params.keystroke_laser_scans,
"Toggle LaserScans Visualization");
413 if (
params.ICP_max_distance > 0)
419 obj->setPose(initial_pose);
420 obj->setName(
"ICP_max_distance");
421 obj->setColor_u8(m_search_disk_color);
423 params.ICP_max_distance,
params.ICP_max_distance - 0.1);
426 this->m_win->unlockAccess3DScene();
427 this->m_win->forceRepaint();
431 if (
params.visualize_laser_scans)
437 laser_scan_viz->enablePoints(
true);
438 laser_scan_viz->enableLine(
true);
439 laser_scan_viz->enableSurface(
true);
440 laser_scan_viz->setSurfaceColor(
441 m_laser_scans_color.R, m_laser_scans_color.G, m_laser_scans_color.B,
442 m_laser_scans_color.A);
444 laser_scan_viz->setName(
"laser_scan_viz");
446 scene->insert(laser_scan_viz);
447 this->m_win->unlockAccess3DScene();
448 this->m_win->forceRepaint();
452 if (this->m_win && this->m_win_manager &&
params.ICP_max_distance > 0)
454 this->m_win_manager->assignTextMessageParameters(
455 &m_offset_y_search_disk, &m_text_index_search_disk);
457 this->m_win_manager->addTextMessage(
458 5, -m_offset_y_search_disk,
mrpt::format(
"ICP Edges search radius"),
460 m_text_index_search_disk);
463 this->m_time_logger.leave(
"CICPCriteriaERD::Visuals");
466 template <
class GRAPH_T>
470 this->m_time_logger.enter(
"CICPCriteriaERD::Visuals");
474 parent_t::updateVisuals();
477 if (this->m_win &&
params.ICP_max_distance > 0)
484 disk_obj->setPose(this->m_graph->nodes[this->m_graph->nodeCount() - 1]);
486 this->m_win->unlockAccess3DScene();
487 this->m_win->forceRepaint();
491 if (this->m_win &&
params.visualize_laser_scans &&
492 (m_last_laser_scan2D || m_fake_laser_scan2D))
501 if (m_fake_laser_scan2D)
503 laser_scan_viz->setScan(*m_fake_laser_scan2D);
507 laser_scan_viz->setScan(*m_last_laser_scan2D);
511 auto search = this->m_graph->nodes.find(this->m_graph->nodeCount() - 1);
512 if (search != this->m_graph->nodes.end())
514 laser_scan_viz->setPose(
515 this->m_graph->nodes[this->m_graph->nodeCount() - 1]);
518 laser_scan_viz->setPose(
CPose3D(
519 laser_scan_viz->getPoseX(), laser_scan_viz->getPoseY(), -0.15,
520 DEG2RAD(laser_scan_viz->getPoseYaw()),
521 DEG2RAD(laser_scan_viz->getPosePitch()),
522 DEG2RAD(laser_scan_viz->getPoseRoll())));
525 this->m_win->unlockAccess3DScene();
526 this->m_win->forceRepaint();
529 this->m_time_logger.leave(
"CICPCriteriaERD::Visuals");
533 template <
class GRAPH_T>
538 using namespace mrpt;
541 "Cannot toggle visibility of specified object.\n " 542 "Make sure that the corresponding visualization flag ( %s " 543 ") is set to true in the .ini file.\n",
545 std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
550 template <
class GRAPH_T>
554 parent_t::loadParams(source_fname);
556 params.loadFromConfigFileName(
557 source_fname,
"EdgeRegistrationDeciderParameters");
562 int min_verbosity_level =
source.read_int(
563 "EdgeRegistrationDeciderParameters",
"class_verbosity", 1,
false);
568 template <
class GRAPH_T>
572 parent_t::printParams();
578 template <
class GRAPH_T>
589 stringstream class_props_ss;
590 class_props_ss <<
"ICP Goodness-based Registration Procedure Summary: " 592 class_props_ss << header_sep << std::endl;
595 const std::string time_res = this->m_time_logger.getStatsAsText();
596 const std::string output_res = this->getLogAsString();
600 parent_t::getDescriptiveReport(report_str);
602 *report_str += class_props_ss.str();
603 *report_str += report_sep;
605 *report_str += time_res;
606 *report_str += report_sep;
608 *report_str += output_res;
609 *report_str += report_sep;
617 template <
class GRAPH_T>
619 : decider(d), keystroke_laser_scans(
"l"), has_read_config(false)
623 template <
class GRAPH_T>
626 template <
class GRAPH_T>
628 std::ostream& out)
const 633 "------------------[ Goodness-based ICP Edge Registration " 634 "]------------------\n");
636 "ICP goodness threshold = %.2f%% \n",
637 ICP_goodness_thresh * 100);
639 "ICP max radius for edge search = %.2f\n", ICP_max_distance);
641 "Min. node difference for LC = %lu\n", LC_min_nodeid_diff);
643 "Visualize laser scans = %d\n", visualize_laser_scans);
645 "3DScans Image Directory = %s\n",
646 scans_img_external_dir.c_str());
650 template <
class GRAPH_T>
656 LC_min_nodeid_diff =
source.read_int(
657 "GeneralConfiguration",
"LC_min_nodeid_diff", 30,
false);
659 source.read_double(section,
"ICP_max_distance", 10,
false);
660 ICP_goodness_thresh =
661 source.read_double(section,
"ICP_goodness_thresh", 0.75,
false);
662 visualize_laser_scans =
source.read_bool(
663 "VisualizationParameters",
"visualize_laser_scans",
true,
false);
664 scans_img_external_dir =
source.read_string(
665 section,
"scan_images_external_directory",
"./",
false);
667 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.
#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.
static Ptr Create(Args &&... args)
void dumpVisibilityErrorMsg(std::string viz_flag, int sleep_time=500)
double DEG2RAD(const double x)
Degrees to radians.
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.
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement, as from a time-of-flight range camera or any other RGBD sensor.
void updateVisuals() override
Update the relevant visual features in CDisplayWindow.
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...
GLsizei GLsizei GLuint * obj
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
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.
float goodness
A goodness measure for the alignment, it is a [0,1] range indicator of percentage of correspondences...
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);
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...
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);
unsigned short nIterations
The number of executed iterations until convergence.
GLsizei const GLchar ** string
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).
void initializeVisuals() override
Initialize visual objects in CDisplayWindow (e.g.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
A RGB color - floats in the range [0,1].
The ICP algorithm return information.
The namespace for 3D scene representation and rendering.
GLsizei GLsizei GLchar * source
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.
GLenum const GLfloat * params
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...
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
typename GRAPH_T::constraint_t constraint_t
Handy typedefs.