Main MRPT website > C++ reference for MRPT 1.9.9
CRandomFieldGridMap3D.cpp
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 #include "maps-precomp.h" // Precomp header
11 
14 #include <mrpt/utils/CTicTac.h>
16 
17 #include <mrpt/config.h>
18 
19 #if MRPT_HAS_VTK
20 #include <vtkStructuredGrid.h>
21 #include <vtkDoubleArray.h>
22 #include <vtkPointData.h>
23 #include <vtkVersion.h>
24 #include <vtkCellArray.h>
25 #include <vtkPoints.h>
26 #include <vtkXMLStructuredGridWriter.h>
27 #include <vtkSmartPointer.h>
28 #endif
29 
30 using namespace mrpt;
31 using namespace mrpt::maps;
32 using namespace mrpt::utils;
33 using namespace std;
34 
36 
37 /*---------------------------------------------------------------
38  Constructor
39  ---------------------------------------------------------------*/
41  double x_min, double x_max, double y_min, double y_max, double z_min,
42  double z_max, double voxel_size, bool call_initialize_now)
44  x_min, x_max, y_min, y_max, z_min, z_max, voxel_size /*xy*/,
45  voxel_size /*z*/),
46  COutputLogger("CRandomFieldGridMap3D")
47 {
48  if (call_initialize_now) this->internal_initialize();
49 }
50 
51 /** Changes the size of the grid, erasing previous contents */
53  const double x_min, const double x_max, const double y_min,
54  const double y_max, const double z_min, const double z_max,
55  const double resolution_xy, const double resolution_z,
56  const TRandomFieldVoxel* fill_value)
57 {
58  MRPT_START;
59 
61  x_min, x_max, y_min, y_max, z_min, z_max, resolution_xy, resolution_z,
62  fill_value);
63  this->internal_initialize();
64 
65  MRPT_END;
66 }
67 
69  double new_x_min, double new_x_max, double new_y_min, double new_y_max,
70  double new_z_min, double new_z_max,
71  const TRandomFieldVoxel& defaultValueNewCells,
72  double additionalMarginMeters)
73 {
74  MRPT_START;
75 
77  new_x_min, new_x_max, new_y_min, new_y_max, new_z_min, new_z_max,
78  defaultValueNewCells, additionalMarginMeters);
79  this->internal_initialize(false);
80 
81  MRPT_END;
82 }
83 
85 {
87  internal_initialize();
88 }
89 
90 void CRandomFieldGridMap3D::internal_initialize(bool erase_prev_contents)
91 {
92  if (erase_prev_contents)
93  {
94  // Set the gridmap (m_map) to initial values:
95  TRandomFieldVoxel def(0, 0); // mean, std
96  fill(def);
97  }
98 
99  // Reset gmrf:
100  m_gmrf.setVerbosityLevel(this->getMinLoggingLevel());
101  if (erase_prev_contents)
102  {
103  m_gmrf.clear();
104  m_mrf_factors_activeObs.clear();
105  }
106  else
107  {
108  // Only remove priors, leave observations:
109  m_gmrf.clearAllConstraintsByType_Binary();
110  }
111  m_mrf_factors_priors.clear();
112 
113  // Initiating prior:
114  const size_t nodeCount = m_map.size();
115  ASSERT_EQUAL_(nodeCount, m_size_x * m_size_y * m_size_z);
116  ASSERT_EQUAL_(m_size_x_times_y, m_size_x * m_size_y);
117 
119  "[internal_initialize] Creating priors for GMRF with "
120  << nodeCount << " nodes." << std::endl);
121  CTicTac tictac;
122  tictac.Tic();
123 
124  m_mrf_factors_activeObs.resize(nodeCount); // Alloc space for obs
125  m_gmrf.initialize(nodeCount);
126 
127  ConnectivityDescriptor* custom_connectivity =
128  m_gmrf_connectivity
129  .get(); // Use a raw ptr to avoid the cost in the inner loops
130 
131  size_t cx = 0, cy = 0, cz = 0;
132  for (size_t j = 0; j < nodeCount; j++)
133  {
134  // add factors between this node and:
135  // 1) the right node: j +1
136  // 2) the back node: j+m_size_x
137  // 3) the top node: j+m_size_x*m_size*y
138  //-------------------------------------------------
139  const size_t c_idx_to_check[3] = {cx, cy, cz};
140  const size_t c_idx_to_check_limits[3] = {m_size_x - 1, m_size_y - 1,
141  m_size_z - 1};
142  const size_t c_neighbor_idx_incr[3] = {1, m_size_x, m_size_x_times_y};
143 
144  for (int dir = 0; dir < 3; dir++)
145  {
146  if (c_idx_to_check[dir] >= c_idx_to_check_limits[dir]) continue;
147 
148  const size_t i = j + c_neighbor_idx_incr[dir];
149  ASSERT_(i < nodeCount);
150 
151  double edge_lamdba = .0;
152  if (custom_connectivity != nullptr)
153  {
154  const bool is_connected =
155  custom_connectivity->getEdgeInformation(
156  this, cx, cy, cz, cx + (dir == 0 ? 1 : 0),
157  cy + (dir == 1 ? 1 : 0), cz + (dir == 2 ? 1 : 0),
158  edge_lamdba);
159  if (!is_connected) continue;
160  }
161  else
162  {
163  edge_lamdba = insertionOptions.GMRF_lambdaPrior;
164  }
165 
166  TPriorFactorGMRF new_prior(*this);
167  new_prior.node_id_i = i;
168  new_prior.node_id_j = j;
169  new_prior.Lambda = edge_lamdba;
170 
171  m_mrf_factors_priors.push_back(new_prior);
172  m_gmrf.addConstraint(
173  *m_mrf_factors_priors.rbegin()); // add to graph
174  }
175 
176  // Increment coordinates:
177  if (++cx >= m_size_x)
178  {
179  cx = 0;
180  if (++cy >= m_size_y)
181  {
182  cy = 0;
183  cz++;
184  }
185  }
186  } // end for "j"
187 
189  "[internal_initialize] Prior built in " << tictac.Tac() << " s\n"
190  << std::endl);
191 }
192 
193 /*---------------------------------------------------------------
194  TInsertionOptions
195  ---------------------------------------------------------------*/
197  : GMRF_lambdaPrior(0.01f), // [GMRF model] The information (Lambda) of
198  // fixed map constraints
199  GMRF_skip_variance(false)
200 {
201 }
202 
204  mrpt::utils::CStream& out) const
205 {
206  out.printf("GMRF_lambdaPrior = %f\n", GMRF_lambdaPrior);
207  out.printf(
208  "GMRF_skip_variance = %s\n",
209  GMRF_skip_variance ? "true" : "false");
210 }
211 
213  const mrpt::utils::CConfigFileBase& iniFile, const std::string& section)
214 {
215  GMRF_lambdaPrior = iniFile.read_double(
216  section.c_str(), "GMRF_lambdaPrior", GMRF_lambdaPrior);
217  GMRF_skip_variance = iniFile.read_bool(
218  section.c_str(), "GMRF_skip_variance", GMRF_skip_variance);
219 }
220 
221 /** Save the current estimated grid to a VTK file (.vts) as a "structured grid".
222  * \sa saveAsCSV */
224  const std::string& fil) const
225 {
226  MRPT_START;
227 #if MRPT_HAS_VTK
228 
229  vtkStructuredGrid* vtkGrid = vtkStructuredGrid::New();
230  this->getAsVtkStructuredGrid(vtkGrid);
231 
232  // Write file
233  vtkSmartPointer<vtkXMLStructuredGridWriter> writer =
234  vtkSmartPointer<vtkXMLStructuredGridWriter>::New();
235  writer->SetFileName(fil.c_str());
236 
237 #if VTK_MAJOR_VERSION <= 5
238  writer->SetInput(vtkGrid);
239 #else
240  writer->SetInputData(vtkGrid);
241 #endif
242 
243  int ret = writer->Write();
244 
245  vtkGrid->Delete();
246 
247  return ret == 0;
248 #else
249  THROW_EXCEPTION("This method requires building MRPT against VTK!");
250 #endif
251  MRPT_END
252 }
253 
255  const std::string& filName_mean, const std::string& filName_stddev) const
256 {
257  CFileOutputStream f_mean, f_stddev;
258 
259  if (!f_mean.open(filName_mean))
260  {
261  return false;
262  }
263  else
264  {
265  f_mean.printf("x coord, y coord, z coord, scalar\n");
266  }
267 
268  if (!filName_stddev.empty())
269  {
270  if (!f_stddev.open(filName_stddev))
271  {
272  return false;
273  }
274  else
275  {
276  f_mean.printf("x coord, y coord, z coord, scalar\n");
277  }
278  }
279 
280  const size_t nodeCount = m_map.size();
281  size_t cx = 0, cy = 0, cz = 0;
282  for (size_t j = 0; j < nodeCount; j++)
283  {
284  const double x = idx2x(cx), y = idx2y(cy), z = idx2z(cz);
285  const double mean_val = m_map[j].mean_value;
286  const double stddev_val = m_map[j].stddev_value;
287 
288  f_mean.printf("%f, %f, %f, %e\n", x, y, z, mean_val);
289 
290  if (f_stddev.is_open())
291  f_stddev.printf("%f, %f, %f, %e\n", x, y, z, stddev_val);
292 
293  // Increment coordinates:
294  if (++cx >= m_size_x)
295  {
296  cx = 0;
297  if (++cy >= m_size_y)
298  {
299  cy = 0;
300  cz++;
301  }
302  }
303  } // end for "j"
304 
305  return true;
306 }
307 
309 {
310  ASSERTMSG_(
311  !m_mrf_factors_activeObs.empty(),
312  "Cannot update a map with no observations!");
313 
314  Eigen::VectorXd x_incr, x_var;
316  x_incr, insertionOptions.GMRF_skip_variance ? NULL : &x_var);
317 
318  ASSERT_(size_t(m_map.size()) == size_t(x_incr.size()));
319  ASSERT_(
321  size_t(m_map.size()) == size_t(x_var.size()));
322 
323  // Update Mean-Variance in the base grid class
324  for (size_t j = 0; j < m_map.size(); j++)
325  {
326  m_map[j].mean_value += x_incr[j];
327  m_map[j].stddev_value =
328  insertionOptions.GMRF_skip_variance ? .0 : std::sqrt(x_var[j]);
329  }
330 }
331 
333  const ConnectivityDescriptor::Ptr& new_connectivity_descriptor)
334 {
335  m_gmrf_connectivity = new_connectivity_descriptor;
336 }
337 
339  /** [in] The value observed in the (x,y,z) position */
340  const double sensorReading,
341  /** [in] The variance of the sensor observation */
342  const double sensorVariance,
343  /** [in] The (x,y,z) location */
344  const mrpt::math::TPoint3D& point,
345  /** [in] Voxel interpolation method: how many voxels will be affected by the
346  reading */
347  const TVoxelInterpolationMethod method,
348  /** [in] Run a global map update after inserting this observatin
349  (algorithm-dependant) */
350  const bool update_map)
351 {
352  MRPT_START;
353 
354  ASSERT_ABOVE_(sensorVariance, .0);
355  ASSERTMSG_(
356  m_mrf_factors_activeObs.size() == m_map.size(),
357  "Trying to insert observation in uninitialized map (!)");
358 
359  const size_t cell_idx =
360  cellAbsIndexFromCXCYCZ(x2idx(point.x), y2idx(point.y), z2idx(point.z));
361  if (cell_idx == INVALID_VOXEL_IDX) return false;
362 
363  TObservationGMRF new_obs(*this);
364  new_obs.node_id = cell_idx;
365  new_obs.obsValue = sensorReading;
366  new_obs.Lambda = 1.0 / sensorVariance;
367 
368  m_mrf_factors_activeObs[cell_idx].push_back(new_obs);
370  *m_mrf_factors_activeObs[cell_idx].rbegin()); // add to graph
371 
372  if (update_map) this->updateMapEstimation();
373 
374  return true;
375 
376  MRPT_END;
377 }
378 
380  mrpt::utils::CStream& out, int* version) const
381 {
382  if (version)
383  *version = 0;
384  else
385  {
387 
388  // To assure compatibility: The size of each cell:
389  uint32_t n = static_cast<uint32_t>(sizeof(TRandomFieldVoxel));
390  out << n;
391 
392  // Save the map contents:
393  n = static_cast<uint32_t>(m_map.size());
394  out << n;
395 
396 // Save the "m_map": This requires special handling for big endian systems:
397 #if MRPT_IS_BIG_ENDIAN
398  for (uint32_t i = 0; i < n; i++)
399  {
400  out << m_map[i].mean_value << m_map[i].stddev_value;
401  }
402 #else
403  // Little endian: just write all at once:
404  out.WriteBuffer(&m_map[0], sizeof(m_map[0]) * m_map.size());
405 #endif
406 
409  }
410 }
411 
413  mrpt::utils::CStream& in, int version)
414 {
415  switch (version)
416  {
417  case 0:
418  {
420 
421  // To assure compatibility: The size of each cell:
422  uint32_t n;
423  in >> n;
424 
425  ASSERT_EQUAL_(n, static_cast<uint32_t>(sizeof(TRandomFieldVoxel)));
426  // Load the map contents:
427  in >> n;
428  m_map.resize(n);
429 
430 // Read the note in writeToStream()
431 #if MRPT_IS_BIG_ENDIAN
432  for (uint32_t i = 0; i < n; i++)
433  in >> m_map[i].mean_value >> m_map[i].stddev_value;
434 #else
435  // Little endian: just read all at once:
436  in.ReadBuffer(&m_map[0], sizeof(m_map[0]) * m_map.size());
437 #endif
440  }
441  break;
442  default:
444  };
445 }
446 
448  vtkStructuredGrid* output, const std::string& label_mean,
449  const std::string& label_stddev) const
450 {
451  MRPT_START;
452 #if MRPT_HAS_VTK
453 
454  const size_t nx = this->getSizeX(), ny = this->getSizeY(),
455  nz = this->getSizeZ();
456 
457  const int num_values = nx * ny * nz;
458 
459  vtkPoints* newPoints = vtkPoints::New();
460 
461  vtkDoubleArray* newData = vtkDoubleArray::New();
462  newData->SetNumberOfComponents(3);
463  newData->SetNumberOfTuples(num_values);
464 
465  vtkDoubleArray* mean_arr = vtkDoubleArray::New();
466  mean_arr->SetNumberOfComponents(1);
467  mean_arr->SetNumberOfTuples(num_values);
468 
469  vtkDoubleArray* std_arr = vtkDoubleArray::New();
470  std_arr->SetNumberOfComponents(1);
471  std_arr->SetNumberOfTuples(num_values);
472 
473  vtkIdType numtuples = newData->GetNumberOfTuples();
474 
475  {
476  size_t cx = 0, cy = 0, cz = 0;
477  for (vtkIdType cc = 0; cc < numtuples; cc++)
478  {
479  const double x = idx2x(cx), y = idx2y(cy), z = idx2z(cz);
480 
481  newData->SetComponent(cc, 0, x);
482  newData->SetComponent(cc, 1, y);
483  newData->SetComponent(cc, 2, z);
484 
485  mean_arr->SetComponent(cc, 0, m_map[cc].mean_value);
486  std_arr->SetComponent(cc, 0, m_map[cc].stddev_value);
487 
488  // Increment coordinates:
489  if (++cx >= m_size_x)
490  {
491  cx = 0;
492  if (++cy >= m_size_y)
493  {
494  cy = 0;
495  cz++;
496  }
497  }
498  }
499  ASSERT_(size_t(m_map.size()) == size_t(numtuples));
500  }
501 
502  newPoints->SetData(newData);
503  newData->Delete();
504 
505  output->SetExtent(0, nx - 1, 0, ny - 1, 0, nz - 1);
506  output->SetPoints(newPoints);
507  newPoints->Delete();
508 
509  mean_arr->SetName(label_mean.c_str());
510  std_arr->SetName(label_stddev.c_str());
511  output->GetPointData()->AddArray(mean_arr);
512  output->GetPointData()->AddArray(std_arr);
513 
514  mean_arr->Delete();
515  std_arr->Delete();
516 
517 #else
518  THROW_EXCEPTION("This method requires building MRPT against VTK!");
519 #endif // VTK
520  MRPT_END;
521 }
522 
523 // ============ TObservationGMRF ===========
525 {
526  return m_parent->m_map[this->node_id].mean_value - this->obsValue;
527 }
529 {
530  return this->Lambda;
531 }
533 {
534  dr_dx = 1.0;
535 }
536 // ============ TPriorFactorGMRF ===========
538 {
539  return m_parent->m_map[this->node_id_i].mean_value -
540  m_parent->m_map[this->node_id_j].mean_value;
541 }
543 {
544  return this->Lambda;
545 }
547  double& dr_dx_i, double& dr_dx_j) const
548 {
549  dr_dx_i = +1.0;
550  dr_dx_j = -1.0;
551 }
#define ASSERT_EQUAL_(__A, __B)
bool GMRF_skip_variance
(Default:false) Skip the computation of the variance, just compute the mean
void dumpToTextStream(mrpt::utils::CStream &out) const
See utils::CLoadableOptions.
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
GLdouble GLdouble z
Definition: glext.h:3872
EIGEN_STRONG_INLINE void fill(const Scalar v)
Definition: eigen_plugins.h:46
#define ASSERT_ABOVE_(__A, __B)
mrpt::graphs::ScalarFactorGraph m_gmrf
std::vector< TRandomFieldVoxel > m_map
The cells.
The virtual base class which provides a unified interface for all persistent objects in MRPT...
Definition: CSerializable.h:44
size_t cellAbsIndexFromCXCYCZ(const int cx, const int cy, const int cz) const
Gets the absolute index of a voxel in the linear container m_map[] from its cx,cy,cz indices, or -1 if out of map bounds (in any dimension).
The contents of each voxel in a CRandomFieldGridMap3D map.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
virtual bool getEdgeInformation(const CRandomFieldGridMap3D *parent, size_t icx, size_t icy, size_t icz, size_t jcx, size_t jcy, size_t jcz, double &out_edge_information)=0
Implement the check of whether node i=(icx,icy,icz) is connected with node j=(jcx,jcy,jcy).
double GMRF_lambdaPrior
The information (Lambda) of fixed map constraints.
#define THROW_EXCEPTION(msg)
void evalJacobian(double &dr_dx) const override
Returns the derivative of the residual wrt the node value.
GLenum GLsizei n
Definition: glext.h:5074
void WriteBuffer(const void *Buffer, size_t Count)
Writes a block of bytes to the stream from Buffer.
Definition: CStream.cpp:64
void internal_initialize(bool erase_prev_contents=true)
Internal: called called after each change of resolution, size, etc.
bool open(const std::string &fileName, bool append=false)
Open the given file for write.
void dyngridcommon_writeToStream(mrpt::utils::CStream &out) const
Serialization of all parameters, except the contents of each voxel (responsability of the derived cla...
virtual void clear()
Erase the contents of all the cells, setting them to their default values (default ctor)...
double getInformation() const override
Return the inverse of the variance of this constraint.
double evaluateResidual() const override
Return the residual/error of this observation.
STL namespace.
double getInformation() const override
Return the inverse of the variance of this constraint.
A 3D rectangular grid of dynamic size which stores any kind of data at each voxel.
void setVoxelsConnectivity(const ConnectivityDescriptor::Ptr &new_connectivity_descriptor)
Sets a custom object to define the connectivity between voxels.
void Tic()
Starts the stopwatch.
Definition: CTicTac.cpp:82
GLfloat GLfloat nz
Definition: glext.h:6292
This class allows loading and storing values and vectors of different types from a configuration text...
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section)
See utils::CLoadableOptions.
double evaluateResidual() const override
Return the residual/error of this observation.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
#define MRPT_END
This CStream derived class allow using a file as a write-only, binary stream.
double Lambda
"Information" of the observation (=inverse of the variance)
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
virtual void resize(double new_x_min, double new_x_max, double new_y_min, double new_y_max, double new_z_min, double new_z_max, const TRandomFieldVoxel &defaultValueNewvoxels, double additionalMarginMeters=2.0) override
Changes the size of the grid, maintaining previous contents.
std::vector< std::deque< TObservationGMRF > > m_mrf_factors_activeObs
Vector with the active observations and their respective Information, for each map cell...
This class implements a high-performance stopwatch.
Definition: CTicTac.h:23
double Lambda
"Information" of the observation (=inverse of the variance)
void clear() override
Erases all added observations and start again with an empty gridmap.
EIGEN_STRONG_INLINE void setSize(size_t row, size_t col)
Changes the size of matrix, maintaining its previous content as possible and padding with zeros where...
double x
X,Y,Z coordinates.
ConnectivityDescriptor::Ptr m_gmrf_connectivity
Empty: default.
GLsizei const GLchar ** string
Definition: glext.h:4101
void readFromStream(mrpt::utils::CStream &in, int version) override
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
void addConstraint(const UnaryFactorVirtualBase &listOfConstraints)
Insert constraints into the GMRF problem.
bool saveAsCSV(const std::string &filName_mean, const std::string &filName_stddev=std::string()) const
Save the current estimated mean values to a CSV file (compatible with Paraview) with fields x y z mea...
#define MRPT_START
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
CRandomFieldGridMap3D represents a 3D regular grid where each voxel is associated one real-valued pro...
GLfloat GLfloat GLfloat GLfloat nx
Definition: glext.h:6296
int x2idx(double x) const
Transform a coordinate values into voxel indexes.
double idx2x(int cx) const
Transform a voxel index into a coordinate value of the voxel central point.
double read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound=false) const
void getAsVtkStructuredGrid(vtkStructuredGrid *output, const std::string &label_mean=std::string("mean"), const std::string &label_stddev=std::string("stddev")) const
Returns the 3D grid contents as an VTK grid.
void dyngridcommon_readFromStream(mrpt::utils::CStream &in)
Serialization of all parameters, except the contents of each voxel (responsability of the derived cla...
bool saveAsVtkStructuredGrid(const std::string &fil) const
Save the current estimated grid to a VTK file (.vts) as a "structured grid".
GLuint in
Definition: glext.h:7274
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const override
Introduces a pure virtual method responsible for writing to a CStream.
double Tac()
Stops the stopwatch.
Definition: CTicTac.cpp:97
#define ASSERT_(f)
GLenum GLint GLint y
Definition: glext.h:3538
bool insertIndividualReading(const double sensorReading, const double sensorVariance, const mrpt::math::TPoint3D &point, const TVoxelInterpolationMethod method, const bool update_map)
Direct update of the map with a reading in a given position of the map.
void updateMapEstimation()
Run the method-specific procedure required to ensure that the mean & variances are up-to-date with al...
GLenum GLint x
Definition: glext.h:3538
GLfloat ny
Definition: glext.h:6292
Lightweight 3D point.
bool is_open()
Returns true if the file was open without errors.
void evalJacobian(double &dr_dx_i, double &dr_dx_j) const override
Returns the derivative of the residual wrt the node values.
unsigned __int32 uint32_t
Definition: rptypes.h:47
#define MRPT_LOG_DEBUG_STREAM(__CONTENTS)
#define ASSERTMSG_(f, __ERROR_MSG)
virtual void setSize(const double x_min, const double x_max, const double y_min, const double y_max, const double z_min, const double z_max, const double resolution_xy, const double resolution_z=-1.0, const TRandomFieldVoxel *fill_value=nullptr) override
Changes the size of the grid, erasing previous contents.If resolution_z<0, the same resolution will b...
void updateEstimation(Eigen::VectorXd &solved_x_inc, Eigen::VectorXd *solved_variances=nullptr)
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
Base class for user-supplied objects capable of describing voxels connectivity, used to build prior f...



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