Main MRPT website > C++ reference for MRPT 1.9.9
CGasConcentrationGridMap2D.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
13 #include <mrpt/math/CMatrix.h>
15 #include <mrpt/utils/CTicTac.h>
16 #include <mrpt/utils/color_maps.h>
17 #include <mrpt/utils/round.h> // round()
20 #include <mrpt/system/datetime.h>
21 #include <mrpt/system/filesystem.h>
22 #include <mrpt/system/os.h>
23 #include <mrpt/opengl/CArrow.h>
25 #include <mrpt/utils/CStream.h>
26 
27 using namespace mrpt;
28 using namespace mrpt::maps;
29 using namespace mrpt::obs;
30 using namespace mrpt::utils;
31 using namespace mrpt::poses;
32 using namespace std;
33 using namespace mrpt::math;
34 
35 // =========== Begin of Map definition ============
37  "CGasConcentrationGridMap2D,gasGrid",
39 
41  : min_x(-2),
42  max_x(2),
43  min_y(-2),
44  max_y(2),
45  resolution(0.10f),
46  mapType(CGasConcentrationGridMap2D::mrKernelDM)
47 {
48 }
49 
53  const std::string& sectionNamePrefix)
54 {
55  // [<sectionNamePrefix>+"_creationOpts"]
56  const std::string sSectCreation =
57  sectionNamePrefix + string("_creationOpts");
58  MRPT_LOAD_CONFIG_VAR(min_x, float, source, sSectCreation);
59  MRPT_LOAD_CONFIG_VAR(max_x, float, source, sSectCreation);
60  MRPT_LOAD_CONFIG_VAR(min_y, float, source, sSectCreation);
61  MRPT_LOAD_CONFIG_VAR(max_y, float, source, sSectCreation);
62  MRPT_LOAD_CONFIG_VAR(resolution, float, source, sSectCreation);
64  sSectCreation, "mapType", mapType);
65 
66  insertionOpts.loadFromConfigFile(
67  source, sectionNamePrefix + string("_insertOpts"));
68 }
69 
71  mrpt::utils::CStream& out) const
72 {
73  out.printf(
74  "MAP TYPE = %s\n",
77  .c_str());
78  LOADABLEOPTS_DUMP_VAR(min_x, float);
79  LOADABLEOPTS_DUMP_VAR(max_x, float);
80  LOADABLEOPTS_DUMP_VAR(min_y, float);
81  LOADABLEOPTS_DUMP_VAR(max_y, float);
82  LOADABLEOPTS_DUMP_VAR(resolution, float);
83 
84  this->insertionOpts.dumpToTextStream(out);
85 }
86 
90 {
92  *dynamic_cast<const CGasConcentrationGridMap2D::TMapDefinition*>(&_def);
94  def.mapType, def.min_x, def.max_x, def.min_y, def.max_y,
95  def.resolution);
96  obj->insertionOptions = def.insertionOpts;
97  return obj;
98 }
99 // =========== End of Map definition Block =========
100 
103 
104 // Short-cut:
105 #define LUT_TABLE (*(LUT.table))
106 
107 /*---------------------------------------------------------------
108  Constructor
109  ---------------------------------------------------------------*/
111  TMapRepresentation mapType, float x_min, float x_max, float y_min,
112  float y_max, float resolution)
113  : CRandomFieldGridMap2D(mapType, x_min, x_max, y_min, y_max, resolution),
114  insertionOptions()
115 {
116  // Override defaults:
117  insertionOptions.GMRF_saturate_min = 0;
118  insertionOptions.GMRF_saturate_max = 1;
119  insertionOptions.GMRF_lambdaObsLoss = 1.0;
120 
121  // Set the grid to initial values (and adjust covariance matrices,...)
122  // Also, calling clear() is mandatory to end initialization of our base
123  // class (read note in CRandomFieldGridMap2D::CRandomFieldGridMap2D)
125 
126  // Create WindGrids with same dimensions that the original map
127  windGrid_module.setSize(x_min, x_max, y_min, y_max, resolution);
128  windGrid_direction.setSize(x_min, x_max, y_min, y_max, resolution);
129 
130  // initialize counter for advection simulation
131  timeLastSimulated = mrpt::system::now();
132 }
133 
134 CGasConcentrationGridMap2D::~CGasConcentrationGridMap2D() {}
135 /*---------------------------------------------------------------
136  clear
137  ---------------------------------------------------------------*/
139 {
140  // Just do the generic clear:
142 
143  // Anything else special for this derived class?
144 
146  {
147  // Set default values of the wind grid
150 
151  /*float S = windGrid_direction.getSizeX() *
152 windGrid_direction.getSizeY();
153 
154  for( unsigned int y=windGrid_direction.getSizeY()/2;
155 y<windGrid_direction.getSizeY(); y++ )
156  {
157  for( unsigned int x=0; x<windGrid_direction.getSizeX(); x++ )
158  {
159  double * wind_cell = windGrid_direction.cellByIndex(x,y);
160  *wind_cell = 3*3.141516/2;
161 }
162  }*/
163 
164  // Generate Look-Up Table of the Gaussian weights due to wind advection.
166  {
167  // mrpt::system::pause();
168  THROW_EXCEPTION("Problem with LUT wind table");
169  }
170  }
171 }
172 
173 /*---------------------------------------------------------------
174  insertObservation
175  ---------------------------------------------------------------*/
177  const CObservation* obs, const CPose3D* robotPose)
178 {
179  MRPT_START
180 
181  CPose2D robotPose2D;
182  CPose3D robotPose3D;
183 
184  if (robotPose)
185  {
186  robotPose2D = CPose2D(*robotPose);
187  robotPose3D = (*robotPose);
188  }
189  else
190  {
191  // Default values are (0,0,0)
192  }
193 
195  {
196  /********************************************************************
197  OBSERVATION TYPE: CObservationGasSensors
198  ********************************************************************/
199  const CObservationGasSensors* o =
200  static_cast<const CObservationGasSensors*>(obs);
201 
202  if (o->sensorLabel.compare(insertionOptions.gasSensorLabel) == 0)
203  {
204  float sensorReading;
205  CPose2D sensorPose;
206 
207  if (o->sensorLabel.compare("MCEnose") == 0 ||
208  o->sensorLabel.compare("Full_MCEnose") == 0)
209  {
213 
214  // Compute the 3D sensor pose in world coordinates:
215  sensorPose = CPose2D(
216  CPose3D(robotPose2D) + CPose3D(it->eNosePoseOnTheRobot));
217 
218  // Compute the sensor reading value (Volts):
219  if (insertionOptions.gasSensorType == 0x0000)
220  { // compute the mean
221  sensorReading = math::mean(it->readingsVoltage);
222  }
223  else
224  {
225  // Look for the correct sensor type
226  size_t i;
227  for (i = 0; i < it->sensorTypes.size(); i++)
228  {
229  if (it->sensorTypes.at(i) ==
231  break;
232  }
233 
234  if (i < it->sensorTypes.size())
235  {
236  sensorReading = it->readingsVoltage[i];
237  }
238  else
239  {
240  cout << "Sensor especified not found, compute default "
241  "mean value"
242  << endl;
243  sensorReading = math::mean(it->readingsVoltage);
244  }
245  }
246  }
247  else //"GDM, RAE_PID, ENOSE_SIMUL
248  {
250  &o->m_readings[0];
251  // Compute the 3D sensor pose in world coordinates:
252  sensorPose = CPose2D(
253  CPose3D(robotPose2D) + CPose3D(it->eNosePoseOnTheRobot));
254  sensorReading = it->readingsVoltage[0];
255  }
256 
257  // Normalization:
258  sensorReading = (sensorReading - insertionOptions.R_min) /
260 
261  // Update the gross estimates of mean/vars for the whole reading
262  // history (see IROS2009 paper):
264  (sensorReading +
268  (square(sensorReading - m_average_normreadings_mean) +
272 
273  // Finally, do the actual map update with that value:
275  sensorReading,
276  mrpt::math::TPoint2D(sensorPose.x(), sensorPose.y()));
277  return true; // Done!
278  } // endif correct "gasSensorLabel"
279  } // end if "CObservationGasSensors"
280 
281  return false;
282  MRPT_END
283 }
284 
285 /*---------------------------------------------------------------
286  computeObservationLikelihood
287  ---------------------------------------------------------------*/
289  const CObservation* obs, const CPose3D& takenFrom)
290 {
291  MRPT_UNUSED_PARAM(obs);
292  MRPT_UNUSED_PARAM(takenFrom);
293 
294  THROW_EXCEPTION("Not implemented yet!");
295 }
296 
297 /*---------------------------------------------------------------
298  Implements the writing to a CStream capability of CSerializable objects
299  ---------------------------------------------------------------*/
301  mrpt::utils::CStream& out, int* version) const
302 {
303  if (version)
304  *version = 5;
305  else
306  {
308 
309  // To assure compatibility: The size of each cell:
310  uint32_t n = static_cast<uint32_t>(sizeof(TRandomFieldCell));
311  out << n;
312 
313  // Save the map contents:
314  n = static_cast<uint32_t>(m_map.size());
315  out << n;
316 
317 // Save the "m_map": This requires special handling for big endian systems:
318 #if MRPT_IS_BIG_ENDIAN
319  for (uint32_t i = 0; i < n; i++)
320  {
321  out << m_map[i].kf_mean << m_map[i].dm_mean
322  << m_map[i].dmv_var_mean;
323  }
324 #else
325  // Little endian: just write all at once:
326  out.WriteBuffer(
327  &m_map[0], sizeof(m_map[0]) *
328  m_map.size()); // TODO: Do this endianness safe!!
329 #endif
330 
331  // Version 1: Save the insertion options:
332  out << uint8_t(m_mapType) << m_cov << m_stackedCov;
333 
341 
342  // New in v3:
345 
346  out << genericMapParams; // v4
347  }
348 }
349 
350 // Aux struct used below (must be at global scope for STL):
352 {
353  float mean, std;
354  float w, wr;
355 };
356 
357 /*---------------------------------------------------------------
358  Implements the reading from a CStream capability of CSerializable objects
359  ---------------------------------------------------------------*/
361  mrpt::utils::CStream& in, int version)
362 {
363  switch (version)
364  {
365  case 0:
366  case 1:
367  case 2:
368  case 3:
369  case 4:
370  case 5:
371  {
372  dyngridcommon_readFromStream(in, version < 5);
373 
374  // To assure compatibility: The size of each cell:
375  uint32_t n;
376  in >> n;
377 
378  if (version < 2)
379  { // Converter from old versions <=1
380  ASSERT_(
381  n == static_cast<uint32_t>(sizeof(TOldCellTypeInVersion1)));
382  // Load the map contents in an aux struct:
383  in >> n;
384  vector<TOldCellTypeInVersion1> old_map(n);
385  in.ReadBuffer(&old_map[0], sizeof(old_map[0]) * old_map.size());
386 
387  // Convert to newer format:
388  m_map.resize(n);
389  for (size_t k = 0; k < n; k++)
390  {
391  m_map[k].kf_mean =
392  (old_map[k].w != 0) ? old_map[k].wr : old_map[k].mean;
393  m_map[k].kf_std =
394  (old_map[k].w != 0) ? old_map[k].w : old_map[k].std;
395  }
396  }
397  else
398  {
400  n, static_cast<uint32_t>(sizeof(TRandomFieldCell)));
401  // Load the map contents:
402  in >> n;
403  m_map.resize(n);
404 
405 // Read the note in writeToStream()
406 #if MRPT_IS_BIG_ENDIAN
407  for (uint32_t i = 0; i < n; i++)
408  in >> m_map[i].kf_mean >> m_map[i].dm_mean >>
409  m_map[i].dmv_var_mean;
410 #else
411  // Little endian: just read all at once:
412  in.ReadBuffer(&m_map[0], sizeof(m_map[0]) * m_map.size());
413 #endif
414  }
415 
416  // Version 1: Insertion options:
417  if (version >= 1)
418  {
419  uint8_t i;
420  in >> i;
422 
423  in >> m_cov >> m_stackedCov;
424 
432  }
433 
434  if (version >= 3)
435  {
436  uint64_t N;
440  }
441 
442  if (version >= 4) in >> genericMapParams;
443 
445  }
446  break;
447  default:
449  };
450 }
451 
452 /*---------------------------------------------------------------
453  TInsertionOptions
454  ---------------------------------------------------------------*/
456  :
457 
458  gasSensorLabel("MCEnose"),
459  enose_id(0), // By default use the first enose
460  gasSensorType(
461  0x0000), // By default use the mean between all e-nose sensors
462  windSensorLabel("windSensor"),
463  useWindInformation(false), // By default dont use wind
464  std_windNoise_phi(0.2f),
465  std_windNoise_mod(0.2f),
466  default_wind_direction(0.0f),
467  default_wind_speed(1.0f)
468 {
469 }
470 
471 /*---------------------------------------------------------------
472  dumpToTextStream
473  ---------------------------------------------------------------*/
475  mrpt::utils::CStream& out) const
476 {
477  out.printf(
478  "\n----------- [CGasConcentrationGridMap2D::TInsertionOptions] "
479  "------------ \n\n");
480  out.printf("[TInsertionOptions.Common] ------------ \n\n");
481  internal_dumpToTextStream_common(
482  out); // Common params to all random fields maps:
483 
484  out.printf("[TInsertionOptions.GasSpecific] ------------ \n\n");
485  out.printf(
486  "gasSensorLabel = %s\n",
487  gasSensorLabel.c_str());
488  out.printf(
489  "enose_id = %u\n", (unsigned)enose_id);
490  out.printf(
491  "gasSensorType = %u\n",
492  (unsigned)gasSensorType);
493  out.printf(
494  "windSensorLabel = %s\n",
495  windSensorLabel.c_str());
496  out.printf(
497  "useWindInformation = %u\n", useWindInformation);
498 
499  out.printf("advectionFreq = %f\n", advectionFreq);
500  out.printf(
501  "default_wind_direction = %f\n",
502  default_wind_direction);
503  out.printf(
504  "default_wind_speed = %f\n", default_wind_speed);
505  out.printf(
506  "std_windNoise_phi = %f\n", std_windNoise_phi);
507  out.printf(
508  "std_windNoise_mod = %f\n", std_windNoise_mod);
509 
510  out.printf("\n");
511 }
512 
513 /*---------------------------------------------------------------
514  loadFromConfigFile
515  ---------------------------------------------------------------*/
517  const mrpt::utils::CConfigFileBase& iniFile, const std::string& section)
518 {
519  // Common data fields for all random fields maps:
520  internal_loadFromConfigFile_common(iniFile, section);
521 
522  // Specific data fields for gasGridMaps
523  gasSensorLabel = iniFile.read_string(
524  section.c_str(), "gasSensorLabel", "Full_MCEnose", true);
525  enose_id = iniFile.read_int(section.c_str(), "enoseID", enose_id);
526  // Read sensor type in hexadecimal
527  {
528  std::string sensorType_str =
529  iniFile.read_string(section.c_str(), "gasSensorType", "-1", true);
530  int tmpSensorType;
531  stringstream convert(sensorType_str);
532  convert >> std::hex >> tmpSensorType;
533 
534  if (tmpSensorType >= 0)
535  {
536  // Valid number found:
537  gasSensorType = tmpSensorType;
538  }
539  else
540  { // fall back to old name, or default to current value:
541  gasSensorType = iniFile.read_int(
542  section.c_str(), "KF_sensorType", gasSensorType, true);
543  }
544  }
545  windSensorLabel = iniFile.read_string(
546  section.c_str(), "windSensorLabel", "Full_MCEnose", true);
547 
548  // Indicates if wind information must be used for Advection Simulation
549  useWindInformation =
550  iniFile.read_bool(section.c_str(), "useWindInformation", "false", true);
551 
552  //(rad) The initial/default value of the wind direction
553  default_wind_direction =
554  iniFile.read_float(section.c_str(), "default_wind_direction", 0, false);
555  //(m/s) The initial/default value of the wind speed
556  default_wind_speed =
557  iniFile.read_float(section.c_str(), "default_wind_speed", 0, false);
558 
559  //(rad) The noise in the wind direction
560  std_windNoise_phi =
561  iniFile.read_float(section.c_str(), "std_windNoise_phi", 0, false);
562  //(m/s) The noise in the wind strenght
563  std_windNoise_mod =
564  iniFile.read_float(section.c_str(), "std_windNoise_mod", 0, false);
565 
566  //(m/s) The noise in the wind strenght
567  advectionFreq =
568  iniFile.read_float(section.c_str(), "advectionFreq", 1, true);
569 }
570 
571 /*---------------------------------------------------------------
572  getAs3DObject
573 ---------------------------------------------------------------*/
575  mrpt::opengl::CSetOfObjects::Ptr& outObj) const
576 {
577  MRPT_START
580  MRPT_END
581 }
582 
583 /*---------------------------------------------------------------
584  getAs3DObject
585 ---------------------------------------------------------------*/
588  mrpt::opengl::CSetOfObjects::Ptr& varObj) const
589 {
590  MRPT_START
592  CRandomFieldGridMap2D::getAs3DObject(meanObj, varObj);
593  MRPT_END
594 }
595 
596 /*---------------------------------------------------------------
597  getWindAs3DObject
598 ---------------------------------------------------------------*/
600  mrpt::opengl::CSetOfObjects::Ptr& windObj) const
601 {
602  // Return an arrow map of the wind state (module(color) and direction).
603  float scale = 0.2f;
604  size_t arrow_separation =
605  5; // distance between arrows, expresed as times the cell resolution
606 
607  // map limits
608  float x_min = getXMin();
609  float x_max = getXMax();
610  float y_min = getYMin();
611  float y_max = getYMax();
612  float resol = getResolution();
613 
614  // Ensure map dimensions match with wind map
615  unsigned int wind_map_size =
617  ASSERT_(
618  wind_map_size ==
620  if (m_map.size() != wind_map_size)
621  {
622  cout << " GAS MAP DIMENSIONS DO NOT MATCH WIND MAP " << endl;
623  // mrpt::system::pause();
624  }
625 
626  unsigned int cx, cy;
627  vector<float> xs, ys;
628 
629  // xs: array of X-axis values
630  xs.resize(floor((x_max - x_min) / (arrow_separation * resol)));
631  for (cx = 0; cx < xs.size(); cx++)
632  xs[cx] = x_min + arrow_separation * resol * cx;
633 
634  // ys: array of X-axis values
635  ys.resize(floor((y_max - y_min) / (arrow_separation * resol)));
636  for (cy = 0; cy < ys.size(); cy++)
637  ys[cy] = y_min + arrow_separation * resol * cy;
638 
639  for (cy = 0; cy < ys.size(); cy++)
640  {
641  for (cx = 0; cx < xs.size(); cx++)
642  {
643  // Cell values [0,inf]:
644  double dir_xy = *windGrid_direction.cellByPos(xs[cx], ys[cy]);
645  double mod_xy = *windGrid_module.cellByPos(xs[cx], ys[cy]);
646 
648  xs[cx], ys[cy], 0, xs[cx] + scale * cos(dir_xy),
649  ys[cy] + scale * sin(dir_xy), 0, 1.15f * scale, 0.3f * scale,
650  0.35f * scale);
651 
652  float r, g, b;
653  jet2rgb(mod_xy, r, g, b);
654  obj->setColor(r, g, b);
655 
656  windObj->insert(obj);
657  }
658  }
659 }
660 
661 /*---------------------------------------------------------------
662  increaseUncertainty
663 ---------------------------------------------------------------*/
665  const double STD_increase_value)
666 {
667  // Increase cell variance
668  // unsigned int cx,cy;
669  // double memory_retention;
670 
672  for (size_t it = 0; it < m_map.size(); it++)
673  {
674  m_stackedCov(it, 0) = m_stackedCov(it, 0) + STD_increase_value;
675  }
676 
677  // Update m_map.kf_std
679 
680  // for (cy=0; cy<m_size_y; cy++)
681  // {
682  // for (cx=0; cx<m_size_x; cx++)
683  // {
684  // // Forgetting_curve --> memory_retention =
685  // exp(-time/memory_relative_strenght)
686  // memory_retention = exp(- mrpt::system::timeDifference(m_map[cx +
687  // cy*m_size_x].last_updated, now()) / memory_relative_strenght);
688  // //Update Uncertainty (STD)
689  // m_map[cx + cy*m_size_x].kf_std = 1 - ( (1-m_map[cx +
690  // cy*m_size_x].updated_std) * memory_retention );
691  // }
692  // }
693 }
694 
695 /*---------------------------------------------------------------
696  simulateAdvection
697 ---------------------------------------------------------------*/
699  const double& STD_increase_value)
700 {
701  /* 1- Ensure we can use Wind Information
702  -------------------------------------------------*/
703  if (!insertionOptions.useWindInformation) return false;
704 
705  // Get time since last simulation
706  double At =
708  cout << endl << " - At since last simulation = " << At << "seconds" << endl;
709  // update time of last updated.
711 
712  /* 3- Build Transition Matrix (SA)
713  This Matrix contains the probabilities of each cell
714  to "be displaced" to other cells by the wind effect.
715  ------------------------------------------------------*/
716  mrpt::utils::CTicTac tictac;
717  size_t i = 0, c = 0;
718  int cell_i_cx, cell_i_cy;
719  float mu_phi, mu_r, mu_modwind;
720  const size_t N = m_map.size();
721  mrpt::math::CMatrix A(N, N);
722  A.fill(0.0);
723  // std::vector<double> row_sum(N,0.0);
724  double* row_sum = (double*)calloc(N, sizeof(double));
725 
726  try
727  {
728  // Ensure map dimensions match with wind map
729  unsigned int wind_map_size =
731  ASSERT_(
732  wind_map_size ==
734  if (N != wind_map_size)
735  {
736  cout << " GAS MAP DIMENSIONS DO NOT MATCH WIND INFORMATION "
737  << endl;
738  // mrpt::system::pause();
739  }
740 
741  tictac.Tic();
742 
743  // Generate Sparse Matrix of the wind advection SA
744  for (i = 0; i < N; i++)
745  {
746  // Cell_i indx and coordinates
747  idx2cxcy(i, cell_i_cx, cell_i_cy);
748 
749  // Read dirwind value of cell i
751  cell_i_cx, cell_i_cy); //[0,2*pi]
752  unsigned int phi_indx = round(mu_phi / LUT.phi_inc);
753 
754  // Read modwind value of cell i
755  mu_modwind =
756  *windGrid_module.cellByIndex(cell_i_cx, cell_i_cy); //[0,inf)
757  mu_r = mu_modwind * At;
758  if (mu_r > LUT.max_r) mu_r = LUT.max_r;
759  unsigned int r_indx = round(mu_r / LUT.r_inc);
760 
761  // Evaluate LUT
762  ASSERT_(phi_indx < LUT.phi_count);
763  ASSERT_(r_indx < LUT.r_count);
764 
765  // define label
766  vector<TGaussianCell>& cells_to_update =
767  LUT_TABLE[phi_indx][r_indx];
768 
769  // Generate Sparse Matrix with the wind weights "SA"
770  for (unsigned int ci = 0; ci < cells_to_update.size(); ci++)
771  {
772  int final_cx = cell_i_cx + cells_to_update[ci].cx;
773  int final_cy = cell_i_cy + cells_to_update[ci].cy;
774  // Check if affected cells is within the map
775  if ((final_cx >= 0) && (final_cx < (int)getSizeX()) &&
776  (final_cy >= 0) && (final_cy < (int)getSizeY()))
777  {
778  int final_idx = final_cx + final_cy * getSizeX();
779 
780  // Add Value to SA Matrix
781  if (cells_to_update[ci].value != 0.0)
782  {
783  A(final_idx, i) = cells_to_update[ci].value;
784  row_sum[final_idx] += cells_to_update[ci].value;
785  }
786  }
787  } // end-for ci
788  } // end-for cell i
789 
790  cout << " - SA matrix computed in " << tictac.Tac() << "s" << endl
791  << endl;
792  }
793  catch (std::exception& e)
794  {
795  cout << " ######### EXCEPTION computing Transition Matrix (A) "
796  "##########\n: "
797  << e.what() << endl;
798  cout << "on cell i= " << i << " c=" << c << endl << endl;
799  return false;
800  }
801 
802  /* Update Mean + Variance as a Gaussian Mixture
803  ------------------------------------------------*/
804  try
805  {
806  tictac.Tic();
807  // std::vector<double> new_means(N,0.0);
808  double* new_means = (double*)calloc(N, sizeof(double));
809  // std::vector<double> new_variances(N,0.0);
810  double* new_variances = (double*)calloc(N, sizeof(double));
811 
812  for (size_t it_i = 0; it_i < N; it_i++)
813  {
814  //--------
815  // mean
816  //--------
817  for (size_t it_j = 0; it_j < N; it_j++)
818  {
819  if (m_map[it_j].kf_mean != 0 && A(it_i, it_j) != 0)
820  {
821  if (row_sum[it_i] >= 1)
822  new_means[it_i] += (A(it_i, it_j) / row_sum[it_i]) *
823  m_map[it_j].kf_mean;
824  else
825  new_means[it_i] += A(it_i, it_j) * m_map[it_j].kf_mean;
826  }
827  }
828 
829  //----------
830  // variance
831  //----------
832  // Consider special case (borders cells)
833  if (row_sum[it_i] < 1)
834  new_variances[it_i] =
835  (1 - row_sum[it_i]) *
837 
838  for (size_t it_j = 0; it_j < N; it_j++)
839  {
840  if (A(it_i, it_j) != 0)
841  {
842  if (row_sum[it_i] >= 1)
843  new_variances[it_i] +=
844  (A(it_i, it_j) / row_sum[it_i]) *
845  (m_stackedCov(it_j, 0) +
846  square(m_map[it_j].kf_mean - new_means[it_i]));
847  else
848  new_variances[it_i] +=
849  A(it_i, it_j) *
850  (m_stackedCov(it_j, 0) +
851  square(m_map[it_j].kf_mean - new_means[it_i]));
852  }
853  }
854  }
855 
856  // Update means and Cov of the Kalman filter state
857  for (size_t it_i = 0; it_i < N; it_i++)
858  {
859  m_map[it_i].kf_mean = new_means[it_i]; // means
860 
861  // Variances
862  // Scale the Current Covariances with the new variances
863  for (size_t it_j = 0; it_j < N; it_j++)
864  {
865  m_stackedCov(it_i, it_j) =
866  (m_stackedCov(it_i, it_j) / m_stackedCov(it_i, it_i)) *
867  new_variances[it_i]; // variances
868  m_stackedCov(it_j, it_i) = m_stackedCov(it_i, it_j);
869  }
870  }
873 
874  cout << " - Mean&Var updated in " << tictac.Tac() << "s" << endl;
875 
876  // Free Memory
877  free(row_sum);
878  free(new_means);
879  free(new_variances);
880  }
881  catch (std::exception& e)
882  {
883  cout << " ######### EXCEPTION Updating Covariances ##########\n: "
884  << e.what() << endl;
885  cout << "on row i= " << i << " column c=" << c << endl << endl;
886  return false;
887  }
888 
889  // cout << " Increasing general STD..." << endl;
890  increaseUncertainty(STD_increase_value);
891 
892  return true;
893 }
894 
895 /*---------------------------------------------------------------
896  build_Gaussian_Wind_Grid
897 ---------------------------------------------------------------*/
898 
900 /** Builds a LookUp table with the values of the Gaussian Weights result of the
901 wind advection
902 * for a specific condition.
903 *
904 * The LUT contains the values of the Gaussian Weigths and the references to
905 the cell indexes to be applied.
906 * Since the LUT is independent of the wind direction and angle, it generates
907 the Gaussian Weights for different configurations
908 * of wind angle and module values.
909 *
910 * To increase precission, each cell of the grid is sub-divided in subcells of
911 smaller size.
912 
913 * cell_i --> Cell origin (We consider our reference system in the bottom left
914 corner of cell_i ).
915  Is the cell that contains the gas measurement which will be
916 propagated by the wind.
917  The wind propagates in the shape of a 2D Gaussian with center in
918 the target cell (cell_j)
919 * cell_j --> Target cell. Is the cell where falls the center of the Gaussian
920 that models the propagation of the gas comming from cell_i.
921 */
922 
923 {
924  cout << endl << "---------------------------------" << endl;
925  cout << " BUILDING GAUSSIAN WIND WEIGHTS " << endl;
926  cout << "---------------------------------" << endl << endl;
927 
928  //-----------------------------
929  // PARAMS
930  //-----------------------------
931  LUT.resolution = getResolution(); // resolution of the grid-cells (m)
932  LUT.std_phi =
934  .std_windNoise_phi; // Standard Deviation in wind Angle (cte)
937  .advectionFreq; // Standard Deviation in wind module (cte)
938  std::string filename = format(
939  "Gaussian_Wind_Weights_res(%f)_stdPhi(%f)_stdR(%f).gz", LUT.resolution,
940  LUT.std_phi, LUT.std_r);
941 
942  // Fixed Params:
943  LUT.phi_inc = M_PIf / 8; // Increment in the wind Angle. (rad)
944  LUT.phi_count =
945  round(2 * M_PI / LUT.phi_inc) + 1; // Number of angles to generate
946  LUT.r_inc = 0.1f; // Increment in the wind Module. (m)
947  LUT.max_r = 2; // maximum distance (m) to simulate
948  LUT.r_count =
949  round(LUT.max_r / LUT.r_inc) + 1; // Number of wind modules to simulate
950 
951  LUT.table = new vector<vector<vector<TGaussianCell>>>(
952  LUT.phi_count,
953  vector<vector<TGaussianCell>>(LUT.r_count, vector<TGaussianCell>()));
954 
955  // LUT.table = new
956  // vector<vector<vector<vector<vector<TGaussianCell>>>>>(LUT.subcell_count,
957  // vector<vector<vector<vector<TGaussianCell>>>>(LUT.subcell_count,
958  // vector<vector<vector<TGaussianCell>>>(LUT.phi_count,
959  // vector<vector<TGaussianCell>>(LUT.r_count,vector<TGaussianCell>()) ) ) );
960 
961  //-----------------------------
962  // Check if file exists
963  //-----------------------------
964 
965  cout << "Looking for file: " << filename.c_str() << endl;
966 
967  if (mrpt::system::fileExists(filename.c_str()))
968  {
969  // file exists. Load lookUptable from file
970  cout << "LookUp table found for this configuration. Loading..." << endl;
972  }
973  else
974  {
975  // file does not exists. Generate LookUp table.
976  cout << "LookUp table NOT found. Generating table..." << endl;
977 
978  bool debug = true;
979  FILE* debug_file;
980 
981  if (debug)
982  {
983  debug_file = fopen("simple_LUT.txt", "w");
984  fprintf(
985  debug_file, " phi_inc = %.4f \n r_inc = %.4f \n", LUT.phi_inc,
986  LUT.r_inc);
987  fprintf(
988  debug_file, " std_phi = %.4f \n std_r = %.4f \n", LUT.std_phi,
989  LUT.std_r);
990  fprintf(debug_file, "[ phi ] [ r ] ---> (cx,cy)=Value\n");
991  fprintf(debug_file, "----------------------------------\n");
992  }
993 
994  // For the different possible angles (phi)
995  for (size_t phi_indx = 0; phi_indx < LUT.phi_count; phi_indx++)
996  {
997  // mean of the phi value
998  float phi = phi_indx * LUT.phi_inc;
999 
1000  // For the different and possibe wind modules (r)
1001  for (size_t r_indx = 0; r_indx < LUT.r_count; r_indx++)
1002  {
1003  // mean of the radius value
1004  float r = r_indx * LUT.r_inc;
1005 
1006  if (debug)
1007  {
1008  fprintf(debug_file, "\n[%.2f] [%.2f] ---> ", phi, r);
1009  }
1010 
1011  // Estimates Cell_i_position
1012  // unsigned int cell_i_cx = 0;
1013  // unsigned int cell_i_cy = 0;
1014  float cell_i_x = LUT.resolution / 2.0;
1015  float cell_i_y = LUT.resolution / 2.0;
1016 
1017  // Estimate target position according to the mean value of wind.
1018  // float x_final = cell_i_x + r*cos(phi);
1019  // float y_final = cell_i_y + r*sin(phi);
1020 
1021  // Determine cell_j coordinates respect to origin_cell
1022  // int cell_j_cx = static_cast<int>(floor(
1023  // (x_final)/LUT.resolution ));
1024  // int cell_j_cy = static_cast<int>(floor(
1025  // (y_final)/LUT.resolution ));
1026  // Center of cell_j
1027  // float cell_j_x = (cell_j_cx+0.5f)*LUT.resolution;
1028  // float cell_j_y = (cell_j_cy+0.5f)*LUT.resolution;
1029  // left bottom corner of cell_j
1030  // float cell_j_xmin = cell_j_x - LUT.resolution/2.0;
1031  // float cell_j_ymin = cell_j_y - LUT.resolution/2.0;
1032 
1033  /* ---------------------------------------------------------------------------------
1034  Generate bounding-box (+/- 3std) to determine which cells
1035  to update
1036  ---------------------------------------------------------------------------------*/
1037  std::vector<double> vertex_x, vertex_y;
1038  vertex_x.resize(14);
1039  vertex_y.resize(14);
1040  // Bounding-Box initialization
1041  double minBBox_x = 1000;
1042  double maxBBox_x = -1000;
1043  double minBBox_y = 1000;
1044  double maxBBox_y = -1000;
1045 
1046  // Consider special case for high uncertainty in PHI. The shape
1047  // of the polygon is a donut.
1048  double std_phi_BBox = LUT.std_phi;
1049  if (std_phi_BBox > M_PI / 3)
1050  {
1051  std_phi_BBox = M_PI / 3; // To avoid problems generating
1052  // the bounding box. For std>pi/3
1053  // the shape is always a donut.
1054  }
1055 
1056  // Calculate bounding box limits
1057  size_t indx = 0;
1058  int sr = 3;
1059  for (int sd = (-3); sd <= (3); sd++)
1060  {
1061  vertex_x[indx] =
1062  cell_i_x +
1063  (r + sr * LUT.std_r) * cos(phi + sd * std_phi_BBox);
1064  if (vertex_x[indx] < minBBox_x) minBBox_x = vertex_x[indx];
1065  if (vertex_x[indx] > maxBBox_x) maxBBox_x = vertex_x[indx];
1066 
1067  vertex_y[indx] =
1068  cell_i_y +
1069  (r + sr * LUT.std_r) * sin(phi + sd * std_phi_BBox);
1070  if (vertex_y[indx] < minBBox_y) minBBox_y = vertex_y[indx];
1071  if (vertex_y[indx] > maxBBox_y) maxBBox_y = vertex_y[indx];
1072 
1073  indx++;
1074  }
1075  sr = -3;
1076  for (int sd = (3); sd >= (-3); sd--)
1077  {
1078  vertex_x[indx] =
1079  cell_i_x +
1080  (r + sr * LUT.std_r) * cos(phi + sd * std_phi_BBox);
1081  if (vertex_x[indx] < minBBox_x) minBBox_x = vertex_x[indx];
1082  if (vertex_x[indx] > maxBBox_x) maxBBox_x = vertex_x[indx];
1083 
1084  vertex_y[indx] =
1085  cell_i_y +
1086  (r + sr * LUT.std_r) * sin(phi + sd * std_phi_BBox);
1087  if (vertex_y[indx] < minBBox_y) minBBox_y = vertex_y[indx];
1088  if (vertex_y[indx] > maxBBox_y) maxBBox_y = vertex_y[indx];
1089 
1090  indx++;
1091  }
1092 
1093  /* ------------------------------------------------------------------------
1094  Determine range of cells to update according to the
1095  Bounding-Box limits.
1096  Origin cell is cx=cy= 0 x[0,res), y[0,res)
1097  ---------------------------------------------------------------------------*/
1098  int min_cx =
1099  static_cast<int>(floor(minBBox_x / LUT.resolution));
1100  int max_cx =
1101  static_cast<int>(floor(maxBBox_x / LUT.resolution));
1102  int min_cy =
1103  static_cast<int>(floor(minBBox_y / LUT.resolution));
1104  int max_cy =
1105  static_cast<int>(floor(maxBBox_y / LUT.resolution));
1106 
1107  int num_cells_affected =
1108  (max_cx - min_cx + 1) * (max_cy - min_cy + 1);
1109 
1110  if (num_cells_affected == 1)
1111  {
1112  // Concentration of cell_i moves to cell_a (cx,cy)
1113  TGaussianCell gauss_info;
1114  gauss_info.cx = min_cx; // since max_cx == min_cx
1115  gauss_info.cy = min_cy;
1116  gauss_info.value = 1; // prob = 1
1117 
1118  // Add cell volume to LookUp Table
1119  LUT_TABLE[phi_indx][r_indx].push_back(gauss_info);
1120 
1121  if (debug)
1122  {
1123  // Save to file (debug)
1124  fprintf(
1125  debug_file, "(%d,%d)=%.4f", gauss_info.cx,
1126  gauss_info.cy, gauss_info.value);
1127  }
1128  }
1129  else
1130  {
1131  // Estimate volume of the Gaussian under each affected cell
1132 
1133  float subcell_pres = LUT.resolution / 10;
1134  // Determine the number of subcells inside the Bounding-Box
1135  const int BB_x_subcells =
1136  (int)(floor((maxBBox_x - minBBox_x) / subcell_pres) + 1);
1137  const int BB_y_subcells =
1138  (int)(floor((maxBBox_y - minBBox_y) / subcell_pres) + 1);
1139 
1140  double subcell_pres_x =
1141  (maxBBox_x - minBBox_x) / BB_x_subcells;
1142  double subcell_pres_y =
1143  (maxBBox_y - minBBox_y) / BB_y_subcells;
1144 
1145  // Save the W value of each cell using a map
1146  std::map<std::pair<int, int>, float> w_values;
1147  std::map<std::pair<int, int>, float>::iterator it;
1148  float sum_w = 0;
1149 
1150  for (int scy = 0; scy < BB_y_subcells; scy++)
1151  {
1152  for (int scx = 0; scx < BB_x_subcells; scx++)
1153  {
1154  // P-Subcell coordinates (center of the p-subcell)
1155  float subcell_a_x =
1156  minBBox_x + (scx + 0.5f) * subcell_pres_x;
1157  float subcell_a_y =
1158  minBBox_y + (scy + 0.5f) * subcell_pres_y;
1159 
1160  // distance and angle between cell_i and subcell_a
1161  float r_ia = sqrt(
1162  square(subcell_a_x - cell_i_x) +
1163  square(subcell_a_y - cell_i_y));
1164  float phi_ia = atan2(
1165  subcell_a_y - cell_i_y, subcell_a_x - cell_i_x);
1166 
1167  // Volume Approximation of subcell_a (Gaussian
1168  // Bivariate)
1169  float w =
1170  (1 / (2 * M_PI * LUT.std_r * LUT.std_phi)) *
1171  exp(-0.5 *
1172  (square(r_ia - r) / square(LUT.std_r) +
1173  square(phi_ia - phi) /
1174  square(LUT.std_phi)));
1175  w += (1 / (2 * M_PI * LUT.std_r * LUT.std_phi)) *
1176  exp(-0.5 *
1177  (square(r_ia - r) / square(LUT.std_r) +
1178  square(phi_ia + 2 * M_PI - phi) /
1179  square(LUT.std_phi)));
1180  w += (1 / (2 * M_PI * LUT.std_r * LUT.std_phi)) *
1181  exp(-0.5 *
1182  (square(r_ia - r) / square(LUT.std_r) +
1183  square(phi_ia - 2 * M_PI - phi) /
1184  square(LUT.std_phi)));
1185 
1186  // Since we work with a cell grid, approximate the
1187  // weight of the gaussian by the volume of the
1188  // subcell_a
1189  if (r_ia != 0.0)
1190  w =
1191  (w * (subcell_pres_x * subcell_pres_y) /
1192  r_ia);
1193 
1194  // Determine cell index of the current subcell
1195  int cell_cx = static_cast<int>(
1196  floor(subcell_a_x / LUT.resolution));
1197  int cell_cy = static_cast<int>(
1198  floor(subcell_a_y / LUT.resolution));
1199 
1200  // Save w value
1201  it =
1202  w_values.find(std::make_pair(cell_cx, cell_cy));
1203  if (it != w_values.end()) // already exists
1204  w_values[std::make_pair(cell_cx, cell_cy)] += w;
1205  else
1206  w_values[std::make_pair(cell_cx, cell_cy)] = w;
1207 
1208  sum_w = sum_w + w;
1209  } // end-for scx
1210  } // end-for scy
1211 
1212  // SAVE to LUT
1213  for (it = w_values.begin(); it != w_values.end(); it++)
1214  {
1215  float w_final =
1216  (it->second) / sum_w; // normalization to 1
1217 
1218  if (w_final >= 0.001)
1219  {
1220  // Save the weight of the gaussian volume for cell_a
1221  // (cx,cy)
1222  TGaussianCell gauss_info;
1223  gauss_info.cx = it->first.first;
1224  gauss_info.cy = it->first.second;
1225  gauss_info.value = w_final;
1226 
1227  // Add cell volume to LookUp Table
1228  LUT_TABLE[phi_indx][r_indx].push_back(gauss_info);
1229 
1230  if (debug)
1231  {
1232  // Save to file (debug)
1233  fprintf(
1234  debug_file, "(%d,%d)=%.6f ",
1235  gauss_info.cx, gauss_info.cy,
1236  gauss_info.value);
1237  }
1238  }
1239  }
1240 
1241  // OLD WAY
1242 
1243  /* ---------------------------------------------------------
1244  Estimate the volume of the Gaussian on each affected cell
1245  //-----------------------------------------------------------*/
1246  // for(int cx=min_cx; cx<=max_cx; cx++)
1247  //{
1248  // for(int cy=min_cy; cy<=max_cy; cy++)
1249  // {
1250  // // Coordinates of affected cell (center of the cell)
1251  // float cell_a_x = (cx+0.5f)*LUT.resolution;
1252  // float cell_a_y = (cy+0.5f)*LUT.resolution;
1253  // float w_cell_a = 0.0; //initial Gaussian value of
1254  // cell afected
1255 
1256  // // Estimate volume of the Gaussian under cell (a)
1257  // // Partition each cell into (p x p) subcells and
1258  // evaluate the gaussian.
1259  // int p = 40;
1260  // float subcell_pres = LUT.resolution/p;
1261  // float cell_a_x_min = cell_a_x - LUT.resolution/2.0;
1262  // float cell_a_y_min = cell_a_y - LUT.resolution/2.0;
1263 
1264  //
1265  // for(int scy=0; scy<p; scy++)
1266  // {
1267  // for(int scx=0; scx<p; scx++)
1268  // {
1269  // //P-Subcell coordinates (center of the
1270  // p-subcell)
1271  // float subcell_a_x = cell_a_x_min +
1272  //(scx+0.5f)*subcell_pres;
1273  // float subcell_a_y = cell_a_y_min +
1274  //(scy+0.5f)*subcell_pres;
1275 
1276  // //distance and angle between cell_i and
1277  // subcell_a
1278  // float r_ia = sqrt(
1279  // square(subcell_a_x-cell_i_x)
1280  //+
1281  // square(subcell_a_y-cell_i_y) );
1282  // float phi_ia = atan2(subcell_a_y-cell_i_y,
1283  // subcell_a_x-cell_i_x);
1284 
1285  // //Volume Approximation of subcell_a
1286  //(Gaussian
1287  // Bivariate)
1288  // float w = (1/(2*M_PI*LUT.std_r*LUT.std_phi))
1289  //*
1290  // exp(-0.5*( square(r_ia-r)/square(LUT.std_r) +
1291  // square(phi_ia-phi)/square(LUT.std_phi) ) );
1292  // w += (1/(2*M_PI*LUT.std_r*LUT.std_phi)) *
1293  // exp(-0.5*( square(r_ia-r)/square(LUT.std_r) +
1294  // square(phi_ia+2*M_PI-phi)/square(LUT.std_phi) ) );
1295  // w += (1/(2*M_PI*LUT.std_r*LUT.std_phi)) *
1296  // exp(-0.5*( square(r_ia-r)/square(LUT.std_r) +
1297  // square(phi_ia-2*M_PI-phi)/square(LUT.std_phi) ) );
1298  //
1299  // //Since we work with a cell grid,
1300  // approximate
1301  // the
1302  // weight of the gaussian by the volume of the subcell_a
1303  // if (r_ia != 0.0)
1304  // w_cell_a = w_cell_a + (w *
1305  // square(subcell_pres)/r_ia);
1306  // }//end-for scx
1307  // }//end-for scy
1308 
1309  // //Save the weight of the gaussian volume for cell_a
1310  //(cx,cy)
1311  // TGaussianCell gauss_info;
1312  // gauss_info.cx = cx;
1313  // gauss_info.cy = cy;
1314  // gauss_info.value = w_cell_a;
1315 
1316  // //Add cell volume to LookUp Table
1317  // LUT_TABLE[phi_indx][r_indx].push_back(gauss_info);
1318 
1319  // if (debug)
1320  // {
1321  // //Save to file (debug)
1322  // fprintf(debug_file, "(%d,%d)=%.6f
1323  //",gauss_info.cx, gauss_info.cy, gauss_info.value);
1324  // }
1325  //
1326  //
1327  // }//end-for cy
1328  //}//end-for cx
1329 
1330  } // end-if only one affected cell
1331 
1332  } // end-for r
1333  } // end-for phi
1334 
1335  if (debug) fclose(debug_file);
1336 
1337  // Save LUT to File
1339 
1340  } // end-if table not available
1341 }
1342 
1344 {
1345  // Save LUT to file
1346  cout << "Saving to File ....";
1347 
1349  format(
1350  "Gaussian_Wind_Weights_res(%f)_stdPhi(%f)_stdR(%f).gz",
1352 
1353  if (!f.fileOpenCorrectly())
1354  {
1355  return false;
1356  cout << "WARNING: Gaussian_Wind_Weights file NOT SAVED" << endl;
1357  }
1358 
1359  try
1360  {
1361  // Save params first
1362  f << LUT.resolution; // cell resolution used
1363  f << LUT.std_phi; // std_phi used
1364  f << LUT.std_r;
1365 
1366  f << LUT.phi_inc; // rad
1367  f << (float)LUT.phi_count;
1368  f << LUT.r_inc; // m
1369  f << LUT.max_r; // maximum distance (m)
1370  f << (float)LUT.r_count;
1371 
1372  // Save Multi-table
1373  // vector< vector< vector<TGaussianCell>>>>> *table;
1374 
1375  for (size_t phi_indx = 0; phi_indx < LUT.phi_count; phi_indx++)
1376  {
1377  for (size_t r_indx = 0; r_indx < LUT.r_count; r_indx++)
1378  {
1379  // save all cell values.
1380  size_t N = LUT_TABLE[phi_indx][r_indx].size();
1381  f << (float)N;
1382 
1383  for (size_t i = 0; i < N; i++)
1384  {
1385  f << (float)LUT_TABLE[phi_indx][r_indx][i].cx;
1386  f << (float)LUT_TABLE[phi_indx][r_indx][i].cy;
1387  f << LUT_TABLE[phi_indx][r_indx][i].value;
1388  }
1389  }
1390  }
1391  cout << "DONE" << endl;
1392  f.close();
1393  return true;
1394  }
1395  catch (exception e)
1396  {
1397  cout << endl
1398  << "------------------------------------------------------------"
1399  << endl;
1400  cout << "EXCEPTION WHILE SAVING LUT TO FILE" << endl;
1401  cout << "Exception = " << e.what() << endl;
1402  f.close();
1403  return false;
1404  }
1405 }
1406 
1408 {
1409  // LOAD LUT from file
1410  cout << "Loading from File ....";
1411 
1412  try
1413  {
1415  format(
1416  "Gaussian_Wind_Weights_res(%f)_stdPhi(%f)_stdR(%f).gz",
1418 
1419  if (!f.fileOpenCorrectly())
1420  {
1421  cout << "WARNING WHILE READING FROM: Gaussian_Wind_Weights" << endl;
1422  return false;
1423  }
1424 
1425  float t_float;
1426  unsigned int t_uint;
1427  // Ensure params from file are correct with the specified in the ini
1428  // file
1429  f >> t_float;
1430  ASSERT_(LUT.resolution == t_float)
1431 
1432  f >> t_float;
1433  ASSERT_(LUT.std_phi == t_float);
1434 
1435  f >> t_float;
1436  ASSERT_(LUT.std_r == t_float);
1437 
1438  f >> t_float;
1439  ASSERT_(LUT.phi_inc == t_float);
1440 
1441  f >> t_float;
1442  t_uint = (unsigned int)t_float;
1443  ASSERT_(LUT.phi_count == t_uint);
1444 
1445  f >> t_float;
1446  ASSERT_(LUT.r_inc == t_float);
1447 
1448  f >> t_float;
1449  ASSERT_(LUT.max_r == t_float);
1450 
1451  f >> t_float;
1452  t_uint = (unsigned int)t_float;
1453  ASSERT_(LUT.r_count == t_uint);
1454 
1455  // Load Multi-table
1456  // vector< vector< vector<TGaussianCell>>>>> *table;
1457 
1458  for (size_t phi_indx = 0; phi_indx < LUT.phi_count; phi_indx++)
1459  {
1460  for (size_t r_indx = 0; r_indx < LUT.r_count; r_indx++)
1461  {
1462  // Number of cells to update
1463  size_t N;
1464  f >> t_float;
1465  N = (size_t)t_float;
1466 
1467  for (size_t i = 0; i < N; i++)
1468  {
1469  TGaussianCell gauss_info;
1470  f >> t_float;
1471  gauss_info.cx = (int)t_float;
1472 
1473  f >> t_float;
1474  gauss_info.cy = (int)t_float;
1475 
1476  f >> gauss_info.value;
1477 
1478  // Add cell volume to LookUp Table
1479  LUT_TABLE[phi_indx][r_indx].push_back(gauss_info);
1480  }
1481  }
1482  }
1483  cout << "DONE" << endl;
1484  return true;
1485  }
1486  catch (exception e)
1487  {
1488  cout << endl
1489  << "------------------------------------------------------------"
1490  << endl;
1491  cout << "EXCEPTION WHILE LOADING LUT FROM FILE" << endl;
1492  cout << "Exception = " << e.what() << endl;
1493  return false;
1494  }
1495 }
#define ASSERT_EQUAL_(__A, __B)
float min_x
See CGasConcentrationGridMap2D::CGasConcentrationGridMap2D.
void internal_clear() override
Erase all the contents of the map.
double getXMax() const
Returns the "x" coordinate of right side of grid map.
Definition: CDynamicGrid.h:260
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:135
Virtual base for specifying the kind and parameters of one map (normally, to be inserted into mrpt::m...
std::string gasSensorLabel
The label of the CObservationGasSensor used to generate the map.
float sigma
The sigma of the "Parzen"-kernel Gaussian.
void getWindAs3DObject(mrpt::opengl::CSetOfObjects::Ptr &windObj) const
Returns the 3D object representing the wind grid information.
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.
IMPLEMENTS_SERIALIZABLE(CGasConcentrationGridMap2D, CRandomFieldGridMap2D, mrpt::maps) CGasConcentrationGridMap2D
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
bool enableSaveAs3DObject
(Default=true) If false, calling CMetricMap::getAs3DObject() will have no effects ...
float KF_defaultCellMeanValue
The default value for the mean of cells&#39; concentration.
int void fclose(FILE *f)
An OS-independent version of fclose.
Definition: os.cpp:272
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:6502
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...
#define THROW_EXCEPTION(msg)
mrpt::utils::CDynamicGrid< double > windGrid_direction
uint16_t enose_id
id for the enose used to generate this map (must be < gasGrid_count)
GLenum GLsizei n
Definition: glext.h:5074
Scalar * iterator
Definition: eigen_plugins.h:26
#define LOADABLEOPTS_DUMP_VAR(variableName, variableType)
Macro for dumping a variable to a stream, within the method "dumpToTextStream(out)" (Variable types a...
This file implements several operations that operate element-wise on individual or pairs of container...
void WriteBuffer(const void *Buffer, size_t Count)
Writes a block of bytes to the stream from Buffer.
Definition: CStream.cpp:64
bool fileExists(const std::string &fileName)
Test if a given file (or directory) exists.
Definition: filesystem.cpp:127
double getYMin() const
Returns the "y" coordinate of top side of grid map.
Definition: CDynamicGrid.h:262
mrpt::math::CMatrixD m_cov
The whole covariance matrix, used for the Kalman Filter map representation.
double getXMin() const
Returns the "x" coordinate of left side of grid map.
Definition: CDynamicGrid.h:258
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:76
size_t getSizeY() const
Returns the vertical size of grid map in cells count.
Definition: CDynamicGrid.h:256
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
TMapRepresentation
The type of map representation to be used, see CRandomFieldGridMap2D for a discussion.
virtual void getAs3DObject(mrpt::opengl::CSetOfObjects::Ptr &outObj) const override
Returns a 3D object representing the map.
STL namespace.
TMapGenericParams genericMapParams
Common params to all maps.
Definition: CMetricMap.h:281
#define M_PI
Definition: bits.h:92
mrpt::maps::CGasConcentrationGridMap2D::TInsertionOptions insertionOpts
Observations insertion options.
float cutoffRadius
The cutoff radius for updating cells.
void fill(const T &value)
Fills all the cells with the same value.
Definition: CDynamicGrid.h:119
void Tic()
Starts the stopwatch.
Definition: CTicTac.cpp:82
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:189
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
void idx2cxcy(const int &idx, int &cx, int &cy) const
Transform a global (linear) cell index value into its corresponding (x,y) cell indexes.
Definition: CDynamicGrid.h:283
virtual void getAs3DObject(mrpt::opengl::CSetOfObjects::Ptr &outObj) const override
Returns a 3D object representing the map (mean)
void recoverMeanAndCov() const
In the KF2 implementation, takes the auxiliary matrices and from them update the cells&#39; mean and std ...
This class allows loading and storing values and vectors of different types from a configuration text...
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
TMapRepresentation m_mapType
The map representation type of this map, as passed in the constructor.
unsigned char uint8_t
Definition: rptypes.h:41
T * cellByPos(double x, double y)
Returns a pointer to the contents of a cell given by its coordinates, or nullptr if it is out of the ...
Definition: CDynamicGrid.h:213
int read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound=false) const
float KF_observationModelNoise
The sensor model noise (in normalized concentration units).
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
float R_min
Limits for normalization of sensor readings.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
void dumpToTextStream(mrpt::utils::CStream &out) const override
This method should clearly display all the contents of the structure in textual form, sending it to a CStream.
#define M_PIf
CGasConcentrationGridMap2D(TMapRepresentation mapType=mrAchim, float x_min=-2, float x_max=2, float y_min=-2, float y_max=2, float resolution=0.1)
Constructor.
double getYMax() const
Returns the "y" coordinate of bottom side of grid map.
Definition: CDynamicGrid.h:264
static Ptr Create(Args &&... args)
Definition: CArrow.h:33
math::TPose3D eNosePoseOnTheRobot
The pose of the sensors on the robot.
#define MRPT_END
float advectionFreq
Indicates if wind information must be used.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
The contents of each cell in a CRandomFieldGridMap2D map.
A helper class that can convert an enum value into its textual representation, and viceversa...
Definition: TEnumType.h:38
uint16_t gasSensorType
The sensor type for the gas concentration map (0x0000 ->mean of all installed sensors, 0x2600, 0x6810, ...)
const GLubyte * c
Definition: glext.h:6313
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
std::vector< TRandomFieldCell > m_map
The cells.
Definition: CDynamicGrid.h:44
Transparently opens a compressed "gz" file and reads uncompressed data from it.
This class implements a high-performance stopwatch.
Definition: CTicTac.h:23
size_t getSizeX() const
Returns the horizontal size of grid map in cells count.
Definition: CDynamicGrid.h:254
mrpt::utils::CDynamicGrid< double > windGrid_module
Gridmaps of the wind Direction/Module.
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const override
Introduces a pure virtual method responsible for writing to a CStream.
std::shared_ptr< CSetOfObjects > Ptr
Definition: CSetOfObjects.h:32
bool simulateAdvection(const double &STD_increase_value)
Implements the transition model of the gasConcentration map using the information of the wind maps...
GLubyte g
Definition: glext.h:6279
This namespace contains representation of robot actions and observations.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
GLubyte GLubyte b
Definition: glext.h:6279
Declares a class derived from "CObservation" that represents a set of readings from gas sensors...
GLsizei const GLchar ** string
Definition: glext.h:4101
T * cellByIndex(unsigned int cx, unsigned int cy)
Returns a pointer to the contents of a cell given by its cell indexes, or nullptr if it is out of the...
Definition: CDynamicGrid.h:234
std::vector< std::vector< std::vector< TGaussianCell > > > * table
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
bool m_hasToRecoverMeanAndCov
Only for the KF2 implementation.
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:405
mrpt::system::TTimeStamp timeLastSimulated
The timestamp of the last time the advection simulation was executed.
#define MRPT_START
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
Definition: CObservation.h:60
unsigned __int64 uint64_t
Definition: rptypes.h:50
double internal_computeObservationLikelihood(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D &takenFrom) override
Internal method called by computeObservationLikelihood()
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define MAP_DEFINITION_REGISTER(_CLASSNAME_STRINGS, _CLASSNAME_WITH_NS)
Registers one map class into TMetricMapInitializer factory.
CRandomFieldGridMap2D represents a 2D grid map where each cell is associated one real-valued property...
#define CFileGZOutputStream
Saves data to a file and transparently compress the data using the given compression level...
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
double getResolution() const
Returns the resolution of the grid map.
Definition: CDynamicGrid.h:266
float KF_covSigma
The "sigma" for the initial covariance value between cells (in meters).
Declares a virtual base class for all metric maps storage classes.
Definition: CMetricMap.h:55
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Definition: CPose2D.h:40
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
Declares a class that represents any robot&#39;s observation.
Definition: CObservation.h:41
bool fileOpenCorrectly()
Returns true if the file was open without errors.
std::vector< TObservationENose > m_readings
One entry per e-nose on the robot.
mrpt::maps::CGasConcentrationGridMap2D::TMapRepresentation mapType
The kind of map representation (see CGasConcentrationGridMap2D::CGasConcentrationGridMap2D) ...
#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
void jet2rgb(const float color_index, float &r, float &g, float &b)
Computes the RGB color components (range [0,1]) for the corresponding color index in the range [0...
Definition: color_maps.cpp:140
virtual void internal_clear() override
Erase all the contents of the map.
GLuint in
Definition: glext.h:7274
bool build_Gaussian_Wind_Grid()
Builds a LookUp table with the values of the Gaussian Weights result of the wind advection for a spec...
uint16_t KF_W_size
[mrKalmanApproximate] The size of the window of neighbor cells.
double mean(const CONTAINER &v)
Computes the mean value of a vector.
double Tac()
Stops the stopwatch.
Definition: CTicTac.cpp:97
GLsizei GLsizei GLchar * source
Definition: glext.h:4082
#define ASSERT_(f)
virtual void increaseUncertainty(const double STD_increase_value)
Increase the kf_std of all cells from the m_map This mehod is usually called by the main_map to simul...
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:25
void dyngridcommon_writeToStream(mrpt::utils::CStream &out) const
Definition: CDynamicGrid.h:348
void loadFromConfigFile_map_specific(const mrpt::utils::CConfigFileBase &source, const std::string &sectionNamePrefix) override
Load all map-specific params.
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
Definition: os.cpp:254
mrpt::math::CMatrixD m_stackedCov
The compressed band diagonal matrix for the KF2 implementation.
GLsizei const GLfloat * value
Definition: glext.h:4117
void dumpToTextStream_map_specific(mrpt::utils::CStream &out) const override
CGasConcentrationGridMap2D represents a PDF of gas concentrations over a 2D area. ...
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
Definition: datetime.cpp:208
#define LUT_TABLE
std::vector< float > readingsVoltage
The set of readings (in volts) from the array of sensors (size of "sensorTypes" is the same that the ...
#define MRPT_LOAD_CONFIG_VAR( variableName, variableType, configFileObject, sectionNameStr)
An useful macro for loading variables stored in a INI-like file under a key with the same name that t...
This class is a "CSerializable" wrapper for "CMatrixFloat".
Definition: CMatrix.h:25
unsigned __int32 uint32_t
Definition: rptypes.h:47
void dyngridcommon_readFromStream(mrpt::utils::CStream &in, bool cast_from_float=false)
Definition: CDynamicGrid.h:355
Lightweight 2D point.
static mrpt::maps::CMetricMap * internal_CreateFromMapDefinition(const mrpt::maps::TMetricMapInitializer &def)
float KF_initialCellStd
The initial standard deviation of each cell&#39;s concentration (will be stored both at each cell&#39;s struc...
EIGEN_STRONG_INLINE double mean() const
Computes the mean of the entire matrix.
float std_windNoise_phi
Frequency for simulating advection (only used.
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
mrpt::maps::CGasConcentrationGridMap2D::TInsertionOptions insertionOptions
bool internal_insertObservation(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D *robotPose=nullptr) override
Internal method called by insertObservation()
struct mrpt::maps::CGasConcentrationGridMap2D::TGaussianWindTable LUT
void insertIndividualReading(const double sensorReading, const mrpt::math::TPoint2D &point, const bool update_map=true, const bool time_invariant=true, const double reading_stddev=.0)
Direct update of the map with a reading in a given position of the map, using the appropriate method ...
std::shared_ptr< CArrow > Ptr
Definition: CArrow.h:33



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