MRPT  1.9.9
CICPCriteriaNRD_impl.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #ifndef CICPCRITERIANRD_IMPL_H
11 #define CICPCRITERIANRD_IMPL_H
12 
14 {
15 // Ctors, Dtors
16 //////////////////////////////////////////////////////////////
17 
18 template <class GRAPH_T>
20  : params(*this) // pass reference to self when initializing the parameters
21 // m_mahal_distance_ICP_odom("Mahalanobis dist (ICP - odom)")
22 {
23  using namespace mrpt::math;
24  this->initializeLoggers("CICPCriteriaNRD");
25 
26  m_is_using_3DScan = false;
27 
31 
32  // m_mahal_distance_ICP_odom.resizeWindow(1000); // use the last X
33  // mahalanobis distance values
34 
35  m_times_used_ICP = 0;
37 
38  this->logFmt(mrpt::system::LVL_DEBUG, "Initialized class object");
39 }
40 template <class GRAPH_T>
42 {
43 }
44 
45 template <class GRAPH_T>
48  mrpt::obs::CSensoryFrame::Ptr observations,
49  mrpt::obs::CObservation::Ptr observation)
50 {
51  MRPT_START;
52  MRPT_UNUSED_PARAM(action);
53  this->m_time_logger.enter("updateState");
54 
55  using namespace mrpt::obs;
56  using namespace mrpt::poses;
57 
58  bool registered_new_node = false;
59 
60  if (observation)
61  { // Observation-Only Rawlog
62  // delegate the action to the method responsible
63  if (IS_CLASS(observation, CObservation2DRangeScan))
64  { // 2D
66  std::dynamic_pointer_cast<CObservation2DRangeScan>(observation);
67  registered_new_node = updateState2D(curr_laser_scan);
68  }
69  else if (IS_CLASS(observation, CObservation3DRangeScan))
70  { // 3D
71  CObservation3DRangeScan::Ptr curr_laser_scan =
72  std::dynamic_pointer_cast<CObservation3DRangeScan>(observation);
73  registered_new_node = updateState3D(curr_laser_scan);
74  }
75  else if (IS_CLASS(observation, CObservationOdometry))
76  { // odometry
77  // if it exists use the odometry information to reject wrong ICP
78  // matches
79  CObservationOdometry::Ptr obs_odometry =
80  std::dynamic_pointer_cast<CObservationOdometry>(observation);
81 
82  // not incremental - gives the absolute odometry reading - no InfMat
83  // either
84  m_curr_odometry_only_pose = obs_odometry->odometry;
87  }
88  }
89  else
90  { // action-observations rawlog
91  // Action part
92  if (action->getBestMovementEstimation())
93  {
94  // if it exists use the odometry information to reject wrong ICP
95  // matches
96  CActionRobotMovement2D::Ptr robot_move =
97  action->getBestMovementEstimation();
98  CPosePDF::Ptr increment = robot_move->poseChange.get_ptr();
99  CPosePDFGaussianInf increment_gaussian;
100  increment_gaussian.copyFrom(*increment);
101  m_latest_odometry_PDF += increment_gaussian;
102  }
103 
104  // observations part
105  if (observations->getObservationByClass<CObservation2DRangeScan>())
106  { // 2D
107  CObservation2DRangeScan::Ptr curr_laser_scan =
108  observations->getObservationByClass<CObservation2DRangeScan>();
109  registered_new_node = updateState2D(curr_laser_scan);
110  }
111  else if (observations->getObservationByClass<CObservation3DRangeScan>())
112  { // 3D - EXPERIMENTAL, has not been tested
113  CObservation3DRangeScan::Ptr curr_laser_scan =
114  observations->getObservationByClass<CObservation3DRangeScan>();
115  registered_new_node = updateState3D(curr_laser_scan);
116  }
117  }
118 
119  this->m_time_logger.leave("updateState");
120  return registered_new_node;
121 
122  MRPT_END;
123 } // end of updateState
124 
125 template <class GRAPH_T>
128 {
129  MRPT_START;
130  bool registered_new_node = false;
131 
132  m_curr_laser_scan2D = scan2d;
133  if (!m_last_laser_scan2D)
134  {
135  // initialize the last_laser_scan here - afterwards updated inside the
136  // checkRegistrationCondition*D method
138  }
139  else
140  {
141  registered_new_node = checkRegistrationCondition2D();
142  }
143 
144  return registered_new_node;
145  MRPT_END;
146 } // end of updateState2D
147 
148 template <class GRAPH_T>
150 {
151  MRPT_START;
152 
153  using namespace mrpt::math;
154 
155  bool registered_new_node = false;
156 
157  // Constraint that *may* update incrementally the m_since_prev_node_PDF.
158  constraint_t rel_edge;
160 
161  this->getICPEdge(
162  *m_last_laser_scan2D, *m_curr_laser_scan2D, &rel_edge, nullptr,
163  &icp_info);
164 
165  // Debugging directives
166  MRPT_LOG_DEBUG(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
168  "ICP Alignment operation:\tnIterations: %d\tgoodness: %.f\n",
169  icp_info.nIterations, icp_info.goodness);
171  "Current ICP constraint: \n\tEdge: %s\n\tNorm: %f",
172  rel_edge.getMeanVal().asString().c_str(), rel_edge.getMeanVal().norm());
174  "Corresponding Odometry constraint: \n\tEdge: %s\n\tNorm: %f",
175  m_latest_odometry_PDF.getMeanVal().asString().c_str(),
176  m_latest_odometry_PDF.getMeanVal().norm());
177 
178  // evaluate the mahalanobis distance of the above..
179  // If over an (adaptive) threshold, trust the odometry
180  double mahal_distance =
181  rel_edge.mahalanobisDistanceTo(m_latest_odometry_PDF);
182  // m_mahal_distance_ICP_odom.addNewMeasurement(mahal_distance);
183 
184  // TODO - Find out a proper criterion
185  // How do I filter out the "bad" 2DRangeScans?
186  // double mahal_distance_lim = m_mahal_distance_ICP_odom.getMedian();
187  // double mahal_distance_lim = m_mahal_distance_ICP_odom.getMean();
188  // double mahal_distance_lim =
189  // m_mahal_distance_ICP_odom.getMean() +
190  // m_mahal_distance_ICP_odom.getStdDev();
191  double mahal_distance_lim = 0.18; // visual introspection
192 
193  //
194  // check whether to use ICP or odometry Edge.
195  //
196  // if the norm of the odometry edge is 0, no odometry edge available
197  // => use ICP
198  if (mahal_distance < mahal_distance_lim ||
199  m_latest_odometry_PDF.getMeanVal().norm() == 0)
200  {
201  MRPT_LOG_DEBUG("Using ICP Edge");
203  }
204  else
205  {
206  MRPT_LOG_DEBUG("Using Odometry Edge");
207  rel_edge.copyFrom(m_latest_odometry_PDF);
209  }
210  MRPT_LOG_DEBUG_FMT("\tMahalanobis Distance = %f", mahal_distance);
212  "Times that the ICP Edge was used: %d/%d", m_times_used_ICP,
214 
215  // update the PDF until last registered node
216  this->m_since_prev_node_PDF += rel_edge;
218  registered_new_node = this->checkRegistrationCondition();
219 
220  // reset the odometry tracking as well.
223 
224  MRPT_LOG_DEBUG("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
225  return registered_new_node;
226  MRPT_END;
227 } // end of checkRegistrationCondition2D
228 
229 template <class GRAPH_T>
232 {
233  THROW_EXCEPTION("Not yet implemented.");
234  return false;
235 } // end of updateState3D
236 
237 template <class GRAPH_T>
239 {
240  THROW_EXCEPTION("Not yet implemented.");
241  return false;
242 } // end of checkRegistrationCondition3D
243 
244 template <class GRAPH_T>
246 {
247  MRPT_START;
248  MRPT_LOG_DEBUG("In checkRegistrationCondition");
249  using namespace mrpt::math;
250 
251  // Criterions for adding a new node
252  // - Covered distance since last node > registration_max_distance
253  // - Angle difference since last node > registration_max_angle
254 
255  bool angle_crit = false;
257  {
258  angle_crit =
259  fabs(wrapToPi(this->m_since_prev_node_PDF.getMeanVal().phi())) >
260  params.registration_max_angle;
261  }
262  bool distance_crit = false;
264  {
265  distance_crit = this->m_since_prev_node_PDF.getMeanVal().norm() >
266  params.registration_max_distance;
267  }
268 
269  // actual check
270  bool registered = false;
271  if (distance_crit || angle_crit)
272  {
273  registered = this->registerNewNodeAtEnd();
274  }
275 
276  return registered;
277  MRPT_END;
278 } // end of checkRegistrationCondition
279 
280 template <class GRAPH_T>
282 {
283  MRPT_START;
284  parent_t::loadParams(source_fname);
285 
286  params.loadFromConfigFileName(
287  source_fname, "NodeRegistrationDeciderParameters");
288  // m_mahal_distance_ICP_odom.loadFromConfigFileName(source_fname,
289  //"NodeRegistrationDeciderParameters");
290 
291  // set the logging level if given by the user
292  mrpt::config::CConfigFile source(source_fname);
293  // Minimum verbosity level of the logger
294  int min_verbosity_level = source.read_int(
295  "NodeRegistrationDeciderParameters", "class_verbosity", 1, false);
296  this->setMinLoggingLevel(mrpt::system::VerbosityLevel(min_verbosity_level));
297  MRPT_LOG_DEBUG("Successfully loaded parameters.");
298  MRPT_END;
299 } // end of loadParams
300 
301 template <class GRAPH_T>
303 {
304  MRPT_START;
306 
307  params.dumpToConsole();
308  // m_mahal_distance_ICP_odom.dumpToConsole();
309 
310  MRPT_END;
311 } // end of printParams
312 
313 template <class GRAPH_T>
315  std::string* report_str) const
316 {
317  MRPT_START;
318  using namespace std;
319 
320  const std::string report_sep(2, '\n');
321  const std::string header_sep(80, '#');
322 
323  // Report on graph
324  stringstream class_props_ss;
325  class_props_ss << "ICP Goodness-based Registration Procedure Summary: "
326  << std::endl;
327  class_props_ss << header_sep << std::endl;
328 
329  // time and output logging
330  const std::string time_res = this->m_time_logger.getStatsAsText();
331  const std::string output_res = this->getLogAsString();
332 
333  // merge the individual reports
334  report_str->clear();
335  parent_t::getDescriptiveReport(report_str);
336 
337  *report_str += class_props_ss.str();
338  *report_str += report_sep;
339 
340  // loggers results
341  *report_str += time_res;
342  *report_str += report_sep;
343 
344  *report_str += output_res;
345  *report_str += report_sep;
346 
347  MRPT_END;
348 } // end of getDescriptiveReport
349 
350 // TParams
351 //////////////////////////////////////////////////////////////
352 template <class GRAPH_T>
354 {
355 }
356 template <class GRAPH_T>
358 {
359 }
360 template <class GRAPH_T>
362  std::ostream& out) const
363 {
364  MRPT_START;
365 
366  using namespace mrpt::math;
367 
368  out << mrpt::format(
369  "------------------[ ICP Fixed Intervals Node Registration "
370  "]------------------\n");
371  out << mrpt::format(
372  "Max distance for registration = %.2f m\n", registration_max_distance);
373  out << mrpt::format(
374  "Max Angle for registration = %.2f deg\n",
375  RAD2DEG(registration_max_angle));
376 
377  decider.range_ops_t::params.dumpToTextStream(out);
378 
379  MRPT_END;
380 }
381 template <class GRAPH_T>
383  const mrpt::config::CConfigFileBase& source, const std::string& section)
384 {
385  MRPT_START;
386 
387  using namespace mrpt::math;
388 
389  registration_max_distance = source.read_double(
390  section, "registration_max_distance", 0.5 /* meter */, false);
391  registration_max_angle = source.read_double(
392  section, "registration_max_angle", 10 /* degrees */, false);
393  registration_max_angle = DEG2RAD(registration_max_angle);
394 
395  // load the icp parameters - from "ICP" section explicitly
396  decider.range_ops_t::params.loadFromConfigFile(source, "ICP");
397 
398  MRPT_END;
399 }
400 } // end of namespace
401 
402 #endif /* end of include guard: CICPCRITERIANRD_IMPL_H */
403 
404 
int m_times_used_ICP
How many times we used the ICP Edge instead of Odometry edge.
void getDescriptiveReport(std::string *report_str) const
Fill the provided string with a detailed report of the decider/optimizer state.
#define MRPT_START
Definition: exceptions.h:262
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
mrpt::obs::CObservation2DRangeScan::Ptr m_last_laser_scan2D
handy laser scans to use in the class methods
VerbosityLevel
Enumeration of available verbosity levels.
double RAD2DEG(const double x)
Radians to degrees.
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string &section)
This method load the options from a ".ini"-like file or memory-stored string list.
virtual void loadParams(const std::string &source_fname)
Load the necessary for the decider/optimizer configuration parameters.
void logFmt(const VerbosityLevel level, const char *fmt,...) const MRPT_printf_format_check(3
Alternative logging method, which mimics the printf behavior.
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
bool updateState2D(mrpt::obs::CObservation2DRangeScan::Ptr observation)
Specialized updateState method used solely when dealing with 2DRangeScan information.
virtual void printParams() const
Print the problem parameters - relevant to the decider/optimizer to the screen in a unified/compact w...
double DEG2RAD(const double x)
Degrees to radians.
void getICPEdge(const mrpt::obs::CObservation2DRangeScan &from, const mrpt::obs::CObservation2DRangeScan &to, constraint_t *rel_edge, const mrpt::poses::CPose2D *initial_pose=nullptr, mrpt::slam::CICP::TReturnInfo *icp_info=nullptr)
Align the 2D range scans provided and fill the potential edge that can transform the one into the oth...
pose_t m_curr_odometry_only_pose
pose_t estimation using only odometry information.
pose_t m_last_odometry_only_pose
pose_t estimation using only odometry information.
This class allows loading and storing values and vectors of different types from ".ini" files easily.
static const std::string header_sep
Separator string to be used in debugging messages.
void setMinLoggingLevel(const VerbosityLevel level)
Set the minimum logging level for which the incoming logs are going to be taken into account...
mrpt::obs::CObservation2DRangeScan::Ptr m_curr_laser_scan2D
Current LaserScan.
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.
ICP-based Fixed Intervals Node Registration.
virtual void getDescriptiveReport(std::string *report_str) const
Fill the provided string with a detailed report of the decider/optimizer state.
STL namespace.
std::string getStatsAsText(const size_t column_width=80) const
Dump all stats to a multi-line text string.
bool registerNewNodeAtEnd()
Same goal as the previous method - uses the m_since_prev_node_PDF as the constraint at the end...
bool checkRegistrationCondition()
Check whether a new node should be registered in the graph.
float goodness
A goodness measure for the alignment, it is a [0,1] range indicator of percentage of correspondences...
Definition: CICP.h:197
void printParams() const
Print the problem parameters - relevant to the decider/optimizer to the screen in a unified/compact w...
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.
void copyFrom(const CPosePDF &o) override
Copy operator, translating if necesary (for example, between particles and gaussian representations) ...
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
Use: MRPT_LOG_DEBUG_FMT("i=%u", i);
This namespace contains representation of robot actions and observations.
constraint_t m_latest_odometry_PDF
Odometry rigid-body transformation since the last accepted LaserScan.
void resetPDF(constraint_t *c)
Reset the given PDF method and assign a fixed high-certainty Covariance/Information matrix...
virtual void initializeLoggers(const std::string &name)
Initialize the COutputLogger, CTimeLogger instances given the name of the decider/optimizer at hand...
double leave(const char *func_name)
End of a named section.
unsigned short nIterations
The number of executed iterations until convergence.
Definition: CICP.h:194
GLsizei const GLchar ** string
Definition: glext.h:4101
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:51
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
std::string getLogAsString() const
Get the history of COutputLogger instance in a string representation.
bool checkRegistrationCondition2D()
Specialized checkRegistrationCondtion method used solely when dealing with 2DRangeScan information...
A Probability Density function (PDF) of a 2D pose as a Gaussian with a mean and the inverse of the c...
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::rtti::CObject) is of the give...
Definition: CObject.h:102
#define MRPT_END
Definition: exceptions.h:266
The ICP algorithm return information.
Definition: CICP.h:190
void loadParams(const std::string &source_fname)
Load the necessary for the decider/optimizer configuration parameters.
GLsizei GLsizei GLchar * source
Definition: glext.h:4082
mrpt::system::CTimeLogger m_time_logger
Time logger instance.
bool checkRegistrationCondition3D()
Specialized checkRegistrationCondition method used solely when dealing with 3DRangeScan information...
An observation of the current (cumulative) odometry for a wheeled robot.
typename GRAPH_T::constraint_t constraint_t
type of graph constraints
bool updateState(mrpt::obs::CActionCollection::Ptr action, mrpt::obs::CSensoryFrame::Ptr observations, mrpt::obs::CObservation::Ptr observation)
Update the decider state using the latest dataset measurements.
GLenum const GLfloat * params
Definition: glext.h:3534
int m_times_used_odom
How many times we used the Odometry Edge instead of the ICP edge.
void dumpToTextStream(std::ostream &out) const
This method should clearly display all the contents of the structure in textual form, sending it to a std::ostream.
bool updateState3D(mrpt::obs::CObservation3DRangeScan::Ptr observation)
Specialized updateState method used solely when dealing with 3DRangeScan information.
void enter(const char *func_name)
Start of a named section.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
constraint_t m_since_prev_node_PDF
Tracking the PDF of the current position of the robot with regards to the <b previous registered node...



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020