Main MRPT website > C++ reference for 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-2017, 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 
13 namespace mrpt
14 {
15 namespace graphslam
16 {
17 namespace deciders
18 {
19 // Ctors, Dtors
20 //////////////////////////////////////////////////////////////
21 
22 template <class GRAPH_T>
24  : params(*this) // pass reference to self when initializing the parameters
25 // m_mahal_distance_ICP_odom("Mahalanobis dist (ICP - odom)")
26 {
27  using namespace mrpt::utils;
28  using namespace mrpt::math;
29  this->initializeLoggers("CICPCriteriaNRD");
30 
31  m_is_using_3DScan = false;
32 
36 
37  // m_mahal_distance_ICP_odom.resizeWindow(1000); // use the last X
38  // mahalanobis distance values
39 
40  m_times_used_ICP = 0;
42 
43  this->logFmt(LVL_DEBUG, "Initialized class object");
44 }
45 template <class GRAPH_T>
47 {
48 }
49 
50 template <class GRAPH_T>
53  mrpt::obs::CSensoryFrame::Ptr observations,
54  mrpt::obs::CObservation::Ptr observation)
55 {
56  MRPT_START;
57  MRPT_UNUSED_PARAM(action);
58  this->m_time_logger.enter("updateState");
59 
60  using namespace mrpt::obs;
61  using namespace mrpt::poses;
62 
63  bool registered_new_node = false;
64 
65  if (observation)
66  { // Observation-Only Rawlog
67  // delegate the action to the method responsible
68  if (IS_CLASS(observation, CObservation2DRangeScan))
69  { // 2D
71  std::dynamic_pointer_cast<CObservation2DRangeScan>(observation);
72  registered_new_node = updateState2D(curr_laser_scan);
73  }
74  else if (IS_CLASS(observation, CObservation3DRangeScan))
75  { // 3D
76  CObservation3DRangeScan::Ptr curr_laser_scan =
77  std::dynamic_pointer_cast<CObservation3DRangeScan>(observation);
78  registered_new_node = updateState3D(curr_laser_scan);
79  }
80  else if (IS_CLASS(observation, CObservationOdometry))
81  { // odometry
82  // if it exists use the odometry information to reject wrong ICP
83  // matches
84  CObservationOdometry::Ptr obs_odometry =
85  std::dynamic_pointer_cast<CObservationOdometry>(observation);
86 
87  // not incremental - gives the absolute odometry reading - no InfMat
88  // either
89  m_curr_odometry_only_pose = obs_odometry->odometry;
92  }
93  }
94  else
95  { // action-observations rawlog
96  // Action part
97  if (action->getBestMovementEstimation())
98  {
99  // if it exists use the odometry information to reject wrong ICP
100  // matches
101  CActionRobotMovement2D::Ptr robot_move =
102  action->getBestMovementEstimation();
103  CPosePDF::Ptr increment = robot_move->poseChange.get_ptr();
104  CPosePDFGaussianInf increment_gaussian;
105  increment_gaussian.copyFrom(*increment);
106  m_latest_odometry_PDF += increment_gaussian;
107  }
108 
109  // observations part
110  if (observations->getObservationByClass<CObservation2DRangeScan>())
111  { // 2D
112  CObservation2DRangeScan::Ptr curr_laser_scan =
113  observations->getObservationByClass<CObservation2DRangeScan>();
114  registered_new_node = updateState2D(curr_laser_scan);
115  }
116  else if (observations->getObservationByClass<CObservation3DRangeScan>())
117  { // 3D - EXPERIMENTAL, has not been tested
118  CObservation3DRangeScan::Ptr curr_laser_scan =
119  observations->getObservationByClass<CObservation3DRangeScan>();
120  registered_new_node = updateState3D(curr_laser_scan);
121  }
122  }
123 
124  this->m_time_logger.leave("updateState");
125  return registered_new_node;
126 
127  MRPT_END;
128 } // end of updateState
129 
130 template <class GRAPH_T>
133 {
134  MRPT_START;
135  bool registered_new_node = false;
136 
137  m_curr_laser_scan2D = scan2d;
138  if (!m_last_laser_scan2D)
139  {
140  // initialize the last_laser_scan here - afterwards updated inside the
141  // checkRegistrationCondition*D method
143  }
144  else
145  {
146  registered_new_node = checkRegistrationCondition2D();
147  }
148 
149  return registered_new_node;
150  MRPT_END;
151 } // end of updateState2D
152 
153 template <class GRAPH_T>
155 {
156  MRPT_START;
157 
158  using namespace mrpt::math;
159  using namespace mrpt::utils;
160 
161  bool registered_new_node = false;
162 
163  // Constraint that *may* update incrementally the m_since_prev_node_PDF.
164  constraint_t rel_edge;
166 
167  this->getICPEdge(
168  *m_last_laser_scan2D, *m_curr_laser_scan2D, &rel_edge, nullptr,
169  &icp_info);
170 
171  // Debugging directives
172  this->logFmt(
173  LVL_DEBUG,
174  ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
175  this->logFmt(
176  LVL_DEBUG, "ICP Alignment operation:\tnIterations: %d\tgoodness: %.f\n",
177  icp_info.nIterations, icp_info.goodness);
178 
179  this->logFmt(
180  LVL_DEBUG, "Current ICP constraint: \n\tEdge: %s\n\tNorm: %f",
181  rel_edge.getMeanVal().asString().c_str(), rel_edge.getMeanVal().norm());
182  this->logFmt(
183  LVL_DEBUG,
184  "Corresponding Odometry constraint: \n\tEdge: %s\n\tNorm: %f",
185  m_latest_odometry_PDF.getMeanVal().asString().c_str(),
186  m_latest_odometry_PDF.getMeanVal().norm());
187 
188  // evaluate the mahalanobis distance of the above..
189  // If over an (adaptive) threshold, trust the odometry
190  double mahal_distance =
191  rel_edge.mahalanobisDistanceTo(m_latest_odometry_PDF);
192  // m_mahal_distance_ICP_odom.addNewMeasurement(mahal_distance);
193 
194  // TODO - Find out a proper criterion
195  // How do I filter out the "bad" 2DRangeScans?
196  // double mahal_distance_lim = m_mahal_distance_ICP_odom.getMedian();
197  // double mahal_distance_lim = m_mahal_distance_ICP_odom.getMean();
198  // double mahal_distance_lim =
199  // m_mahal_distance_ICP_odom.getMean() +
200  // m_mahal_distance_ICP_odom.getStdDev();
201  double mahal_distance_lim = 0.18; // visual introspection
202 
203  //
204  // check whether to use ICP or odometry Edge.
205  //
206  // if the norm of the odometry edge is 0, no odometry edge available
207  // => use ICP
208  if (mahal_distance < mahal_distance_lim ||
209  m_latest_odometry_PDF.getMeanVal().norm() == 0)
210  {
211  this->logFmt(LVL_DEBUG, "Using ICP Edge");
213  }
214  else
215  {
216  this->logFmt(LVL_DEBUG, "Using Odometry Edge");
217  rel_edge.copyFrom(m_latest_odometry_PDF);
219  }
220  this->logFmt(LVL_DEBUG, "\tMahalanobis Distance = %f", mahal_distance);
221  this->logFmt(
222  LVL_DEBUG, "Times that the ICP Edge was used: %d/%d", m_times_used_ICP,
224 
225  // update the PDF until last registered node
226  this->m_since_prev_node_PDF += rel_edge;
228  registered_new_node = this->checkRegistrationCondition();
229 
230  // reset the odometry tracking as well.
233 
234  this->logFmt(
235  LVL_DEBUG,
236  "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
237  return registered_new_node;
238  MRPT_END;
239 } // end of checkRegistrationCondition2D
240 
241 template <class GRAPH_T>
244 {
245  THROW_EXCEPTION("Not yet implemented.");
246  return false;
247 } // end of updateState3D
248 
249 template <class GRAPH_T>
251 {
252  THROW_EXCEPTION("Not yet implemented.");
253  return false;
254 } // end of checkRegistrationCondition3D
255 
256 template <class GRAPH_T>
258 {
259  MRPT_START;
260  using namespace mrpt::utils;
261  this->logFmt(LVL_DEBUG, "In checkRegistrationCondition");
262  using namespace mrpt::math;
263 
264  // Criterions for adding a new node
265  // - Covered distance since last node > registration_max_distance
266  // - Angle difference since last node > registration_max_angle
267 
268  bool angle_crit = false;
270  {
271  angle_crit =
272  fabs(wrapToPi(this->m_since_prev_node_PDF.getMeanVal().phi())) >
273  params.registration_max_angle;
274  }
275  bool distance_crit = false;
277  {
278  distance_crit = this->m_since_prev_node_PDF.getMeanVal().norm() >
279  params.registration_max_distance;
280  }
281 
282  // actual check
283  bool registered = false;
284  if (distance_crit || angle_crit)
285  {
286  registered = this->registerNewNodeAtEnd();
287  }
288 
289  return registered;
290  MRPT_END;
291 } // end of checkRegistrationCondition
292 
293 template <class GRAPH_T>
295 {
296  MRPT_START;
297  parent_t::loadParams(source_fname);
298 
299  using namespace mrpt::utils;
300 
301  params.loadFromConfigFileName(
302  source_fname, "NodeRegistrationDeciderParameters");
303  // m_mahal_distance_ICP_odom.loadFromConfigFileName(source_fname,
304  //"NodeRegistrationDeciderParameters");
305 
306  // set the logging level if given by the user
307  CConfigFile source(source_fname);
308  // Minimum verbosity level of the logger
309  int min_verbosity_level = source.read_int(
310  "NodeRegistrationDeciderParameters", "class_verbosity", 1, false);
311  this->setMinLoggingLevel(VerbosityLevel(min_verbosity_level));
312  this->logFmt(LVL_DEBUG, "Successfully loaded parameters.");
313  MRPT_END;
314 } // end of loadParams
315 
316 template <class GRAPH_T>
318 {
319  MRPT_START;
321 
322  params.dumpToConsole();
323  // m_mahal_distance_ICP_odom.dumpToConsole();
324 
325  MRPT_END;
326 } // end of printParams
327 
328 template <class GRAPH_T>
330  std::string* report_str) const
331 {
332  MRPT_START;
333  using namespace std;
334 
335  const std::string report_sep(2, '\n');
336  const std::string header_sep(80, '#');
337 
338  // Report on graph
339  stringstream class_props_ss;
340  class_props_ss << "ICP Goodness-based Registration Procedure Summary: "
341  << std::endl;
342  class_props_ss << header_sep << std::endl;
343 
344  // time and output logging
345  const std::string time_res = this->m_time_logger.getStatsAsText();
346  const std::string output_res = this->getLogAsString();
347 
348  // merge the individual reports
349  report_str->clear();
350  parent_t::getDescriptiveReport(report_str);
351 
352  *report_str += class_props_ss.str();
353  *report_str += report_sep;
354 
355  // loggers results
356  *report_str += time_res;
357  *report_str += report_sep;
358 
359  *report_str += output_res;
360  *report_str += report_sep;
361 
362  MRPT_END;
363 } // end of getDescriptiveReport
364 
365 // TParams
366 //////////////////////////////////////////////////////////////
367 template <class GRAPH_T>
369 {
370 }
371 template <class GRAPH_T>
373 {
374 }
375 template <class GRAPH_T>
377  mrpt::utils::CStream& out) const
378 {
379  MRPT_START;
380 
381  using namespace mrpt::utils;
382  using namespace mrpt::math;
383 
384  out.printf(
385  "------------------[ ICP Fixed Intervals Node Registration "
386  "]------------------\n");
387  out.printf(
388  "Max distance for registration = %.2f m\n", registration_max_distance);
389  out.printf(
390  "Max Angle for registration = %.2f deg\n",
391  RAD2DEG(registration_max_angle));
392 
393  decider.range_ops_t::params.dumpToTextStream(out);
394 
395  MRPT_END;
396 }
397 template <class GRAPH_T>
399  const mrpt::utils::CConfigFileBase& source, const std::string& section)
400 {
401  MRPT_START;
402 
403  using namespace mrpt::utils;
404  using namespace mrpt::math;
405 
406  registration_max_distance = source.read_double(
407  section, "registration_max_distance", 0.5 /* meter */, false);
408  registration_max_angle = source.read_double(
409  section, "registration_max_angle", 10 /* degrees */, false);
410  registration_max_angle = DEG2RAD(registration_max_angle);
411 
412  // load the icp parameters - from "ICP" section explicitly
413  decider.range_ops_t::params.loadFromConfigFile(source, "ICP");
414 
415  MRPT_END;
416 }
417 }
418 }
419 } // end of namespace
420 
421 #endif /* end of include guard: CICPCRITERIANRD_IMPL_H */
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.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
mrpt::obs::CObservation2DRangeScan::Ptr m_last_laser_scan2D
handy laser scans to use in the class methods
virtual void loadParams(const std::string &source_fname)
Load the necessary for the decider/optimizer configuration parameters.
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...
This class allows loading and storing values and vectors of different types from ".ini" files easily.
Definition: CConfigFile.h:35
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...
#define THROW_EXCEPTION(msg)
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.
static const std::string header_sep
Separator string to be used in debugging messages.
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.
std::shared_ptr< CObservation3DRangeScan > Ptr
virtual void getDescriptiveReport(std::string *report_str) const
Fill the provided string with a detailed report of the decider/optimizer state.
STL namespace.
std::shared_ptr< CObservation2DRangeScan > Ptr
std::shared_ptr< CObservationOdometry > Ptr
This class allows loading and storing values and vectors of different types from a configuration text...
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:202
void printParams() const
Print the problem parameters - relevant to the decider/optimizer to the screen in a unified/compact w...
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
GRAPH_T::constraint_t constraint_t
type of graph constraints
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
std::shared_ptr< CPosePDF > Ptr
Definition: CPosePDF.h:44
void copyFrom(const CPosePDF &o) override
Copy operator, translating if necesary (for example, between particles and gaussian representations) ...
#define MRPT_END
std::shared_ptr< CActionRobotMovement2D > Ptr
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
std::string getStatsAsText(const size_t column_width=80) const
Dump all stats to a multi-line text string.
This namespace contains representation of robot actions and observations.
std::shared_ptr< CSensoryFrame > Ptr
Definition: CSensoryFrame.h:56
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...
std::shared_ptr< CObservation > Ptr
Definition: CObservation.h:43
#define DEG2RAD
unsigned short nIterations
The number of executed iterations until convergence.
Definition: CICP.h:199
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:53
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
bool checkRegistrationCondition2D()
Specialized checkRegistrationCondtion method used solely when dealing with 2DRangeScan information...
#define MRPT_START
#define RAD2DEG
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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::shared_ptr< CActionCollection > Ptr
mrpt::utils::CTimeLogger m_time_logger
Time logger instance.
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::utils::CSerializable) is of t...
Definition: CObject.h:103
The ICP algorithm return information.
Definition: CICP.h:195
void loadParams(const std::string &source_fname)
Load the necessary for the decider/optimizer configuration parameters.
GLsizei GLsizei GLchar * source
Definition: glext.h:4082
double leave(const char *func_name)
End of a named section.
Definition: CTimeLogger.h:123
bool checkRegistrationCondition3D()
Specialized checkRegistrationCondition method used solely when dealing with 3DRangeScan information...
An observation of the current (cumulative) odometry for a wheeled robot.
void dumpToTextStream(mrpt::utils::CStream &out) const
This method should clearly display all the contents of the structure in textual form, sending it to a CStream.
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section)
This method load the options from a ".ini"-like file or memory-stored string list.
void enter(const char *func_name)
Start of a named section.
Definition: CTimeLogger.h:117
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.
virtual int printf(const char *fmt,...) MRPT_printf_format_check(2
Writes a string to the stream in a textual form.
Definition: CStream.cpp:597
bool updateState3D(mrpt::obs::CObservation3DRangeScan::Ptr observation)
Specialized updateState method used solely when dealing with 3DRangeScan information.
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: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019