utest/ui/IO.cpp
Go to the documentation of this file.
1 #include "../utest.h"
2 
3 using namespace std;
4 using namespace PointMatcherSupport;
5 
6 //---------------------------
7 // Tests for IO
8 //---------------------------
9 
10 TEST(IOTest, loadYaml)
11 {
12 
13  // Test loading configuration files for data filters
14  std::ifstream ifs0((dataPath + "default-convert.yaml").c_str());
16 
17  // Test loading configuration files for ICP
18  PM::ICP icp;
19 
20  std::ifstream ifs1((dataPath + "default.yaml").c_str());
21  EXPECT_NO_THROW(icp.loadFromYaml(ifs1));
22 
23  std::ifstream ifs2((dataPath + "unit_tests/badIcpConfig_InvalidParameter.yaml").c_str());
25 
26  std::ifstream ifs3((dataPath + "unit_tests/badIcpConfig_InvalidModuleType.yaml").c_str());
28 
29  std::ifstream ifs4((dataPath + "add_descriptor_config.yaml").c_str());
31 }
32 
33 TEST(IOTest, loadCSV)
34 {
35  typedef PointMatcherIO<NumericType> IO;
36  std::istringstream is;
37  std::ostringstream os;
38  DP pts;
39 
40  // too many elements on a line
41  os.clear();
42  os.str("");
43  os <<
44  "x, y\n"
45  "1, 2\n"
46  "1, 2, 3\n"
47  "1, 2\n"
48  ;
49 
50  is.clear();
51  is.str(os.str());
52  EXPECT_THROW(IO::loadCSV(is), runtime_error);
53 
54  // not enough elements on a line
55  os.clear();
56  os.str("");
57  os <<
58  "x, y\n"
59  "1, 2\n"
60  "1, \n"
61  "1, 2\n"
62  ;
63 
64  is.clear();
65  is.str(os.str());
66  EXPECT_THROW(IO::loadCSV(is), runtime_error);
67 
68  // 2D data
69  os.clear();
70  os.str("");
71  os <<
72  "x, y\n"
73  "1, 2\n"
74  "1, 2\n"
75  "8, 2\n"
76  "1, 2\n"
77  ;
78 
79  is.clear();
80  is.str(os.str());
81  pts = IO::loadCSV(is);
82  EXPECT_EQ(4u, pts.getNbPoints());
83  EXPECT_EQ(2u, pts.getEuclideanDim());
84  EXPECT_EQ(0u, pts.getDescriptorDim());
85  EXPECT_EQ(0u, pts.getTimeDim());
86  EXPECT_EQ(8.0, pts.features(0,2));
87 
88  // 3D data
89  os.clear();
90  os.str("");
91  os <<
92  "x, y, z\n"
93  "1, 2, 3\n"
94  "1, 2, 3\n"
95  "8, 2, 3\n"
96  "1, 2, 3\n"
97  ;
98 
99  is.clear();
100  is.str(os.str());
101  pts = IO::loadCSV(is);
102  EXPECT_EQ(4u, pts.getNbPoints());
103  EXPECT_EQ(3u, pts.getEuclideanDim());
104  EXPECT_EQ(0u, pts.getDescriptorDim());
105  EXPECT_EQ(0u, pts.getTimeDim());
106  EXPECT_EQ(8.0, pts.features(0,2));
107 
108  // 3D data with unknown descriptor
109  os.clear();
110  os.str("");
111  os <<
112  "x, y, z, dummy\n"
113  "1, 2, 3, 4\n"
114  "1, 2, 3, 4\n"
115  "8, 2, 3, 4\n"
116  "1, 2, 3, 4\n"
117  ;
118 
119  is.clear();
120  is.str(os.str());
121  pts = IO::loadCSV(is);
122  EXPECT_EQ(4u, pts.getNbPoints());
123  EXPECT_EQ(3u, pts.getEuclideanDim());
124  EXPECT_EQ(1u, pts.getDescriptorDim());
125  EXPECT_EQ(0u, pts.getTimeDim());
126  EXPECT_TRUE(pts.descriptorExists("dummy"));
127 
128  // 3D data with known descriptor
129  os.clear();
130  os.str("");
131  os <<
132  "x, y, z, nx, ny, nz\n"
133  "1, 2, 3, 4, 5, 6\n"
134  "1, 2, 3, 4, 5, 6\n"
135  "8, 2, 3, 4, 5, 6\n"
136  "1, 2, 3, 4, 5, 6\n"
137  ;
138 
139  is.clear();
140  is.str(os.str());
141  pts = IO::loadCSV(is);
142  EXPECT_EQ(4u, pts.getNbPoints());
143  EXPECT_EQ(3u, pts.getEuclideanDim());
144  EXPECT_EQ(3u, pts.getDescriptorDim());
146  EXPECT_EQ(0u, pts.getTimeDim());
147  EXPECT_TRUE(pts.descriptorExists("normals"));
148 
149  // csv with time
150  int64_t time0 = 1410264593275569438;
151  int64_t time1 = 1410264593325569391;
152  int64_t time2 = 1410264593425569295;
153  int64_t time3 = 1410264593522569417;
154 
155  os.clear();
156  os.str("");
157  os <<
158  "x, y, z, time\n"
159  "1, 1, 1, " << time0 << "\n"
160  "2, 1, 1, " << time1 << "\n"
161  "3, 1, 1, " << time2 << "\n"
162  "4, 1, 1, " << time3 << "\n"
163  ;
164 
165  is.clear();
166  is.str(os.str());
167 
168  pts = IO::loadCSV(is);
169  EXPECT_EQ(4u, pts.getNbPoints());
170  EXPECT_EQ(3u, pts.getEuclideanDim());
171  EXPECT_EQ(0u, pts.getDescriptorDim());
172  EXPECT_EQ(1u, pts.getTimeDim());
173  EXPECT_EQ(time3, pts.times(0,3));
174 
175  //cout << "dim: " << pts.getEuclideanDim() << endl;
176  //cout << "nb pts: " << pts.getNbPoints() << endl;
177  //cout << "desc dim: " << pts.getDescriptorDim() << endl;
178  //cout << "time dim: " << pts.getTimeDim() << endl;
179 
180 
181 
182 }
183 
184 TEST(IOTest, loadPLY)
185 {
186  typedef PointMatcherIO<NumericType> IO;
187  std::istringstream is;
188 
189  is.str(
190  ""
191  );
192 
193  EXPECT_THROW(IO::loadPLY(is), runtime_error);
194 
195  is.clear();
196  is.str(
197  "ply\n"
198  "format binary_big_endian 1.0\n"
199  );
200 
201  EXPECT_THROW(IO::loadPLY(is), runtime_error);
202 
203  is.clear();
204  is.str(
205  "ply\n"
206  "format ascii 2.0\n"
207  );
208 
209  EXPECT_THROW(IO::loadPLY(is), runtime_error);
210 
211  is.clear();
212  is.str(
213  "ply\n"
214  "format ascii 1.0\n"
215  );
216 
217  EXPECT_THROW(IO::loadPLY(is), runtime_error);
218 
219  is.clear();
220  is.str(
221  "ply\n"
222  "format ascii 1.0\n"
223  "element vertex 5\n"
224  "\n" //empty line
225  "property float z\n" // wrong order
226  "property float y\n"
227  "property float x\n"
228  "property float grrrr\n" //unknown property
229  "property float nz\n" // wrong order
230  "property float ny\n"
231  "property float nx\n"
232  "end_header\n"
233  "3 2 1 99 33 22 11\n"
234  "3 2 1 99 33 22 11\n"
235  "\n" //empty line
236  "3 2 1 99 33 22 11 3 2 1 99 33 22 11\n" // no line break
237  "3 2 1 99 33 22 11\n"
238 
239  );
240 
241  DP pointCloud = IO::loadPLY(is);
242 
243  // Confirm sizes and dimensions
244  EXPECT_TRUE(pointCloud.features.cols() == 5);
245  EXPECT_TRUE(pointCloud.features.rows() == 4); //x, y, z, pad
246  EXPECT_TRUE(pointCloud.descriptors.cols() == 5);
247  EXPECT_TRUE(pointCloud.descriptors.rows() == 4);//nx, ny, nz, grrrr
248 
249  // Random value check
250  EXPECT_TRUE(pointCloud.features(0, 0) == 1);
251  EXPECT_TRUE(pointCloud.features(2, 2) == 3);
252  EXPECT_TRUE(pointCloud.descriptors(1, 1) == 22);
253  EXPECT_TRUE(pointCloud.descriptors(2, 4) == 33);
254 
255 }
256 
257 
258 TEST(IOTest, loadPCD)
259 {
260  typedef PointMatcherIO<NumericType> IO;
261  std::istringstream is;
262 
263  // Empty file
264  is.str(
265  ""
266  );
267 
268  EXPECT_THROW(IO::loadPCD(is), runtime_error);
269 
270  // Partial header
271  is.clear();
272  is.str(
273  "# .PCD v.7 - Point Cloud Data file format\n"
274  "VERSION .7\n"
275  );
276 
277  EXPECT_THROW(IO::loadPCD(is), runtime_error);
278 
279  // Missing data
280  is.clear();
281  is.str(
282  "# .PCD v.7 - Point Cloud Data file format\n"
283  "VERSION .7\n"
284  "FIELDS x y z\n"
285  "SIZE 4 4 4\n"
286  "TYPE F F F\n"
287  "COUNT 1 1 1\n"
288  "WIDTH 18\n"
289  "HEIGHT 1\n"
290  "VIEWPOINT 0 0 0 1 0 0 0\n"
291  "POINTS 18\n"
292  "DATA ascii\n"
293  );
294 
295  EXPECT_THROW(IO::loadPCD(is), runtime_error);
296 
297 
298  is.clear();
299  is.str(
300  "# .PCD v.7 - Point Cloud Data file format\n"
301  "VERSION .7\n"
302  "FIELDS x y z grrr\n"
303  "SIZE 4 4 4 4\n"
304  "TYPE F F F F\n"
305  "COUNT 1 1 1 1\n"
306  "WIDTH 18\n"
307  "HEIGHT 1\n"
308  "VIEWPOINT 0 0 0 1 0 0 0\n"
309  "POINTS 18\n"
310  "DATA ascii\n"
311  "0.44912094 0.49084857 1.153 22\n"
312  "0.34907714 0.48914573 1.149 22\n"
313  "0.33813429 0.48914573 1.149 22\n"
314  "0.32833049 0.49084857 1.153 22\n"
315  "0.24395333 0.42856666 0.98900002 22\n"
316  "0.20816095 0.42856666 0.98900002 22\n"
317  "0.1987419 0.42291525 0.98900002 22\n"
318  "0.18178761 0.42291525 0.98900002 22\n"
319  "0.17990381 0.42291525 0.98900002 22\n"
320  "-0.035590474 0.42997143 1.01 22\n"
321  "-0.035907622 0.43962574 1.0190001 22\n"
322  "-0.043542858 0.43639618 1.016 22\n"
323  "-0.15246001 0.36058003 0.84700006 22\n"
324  "0.21956001 0.44007048 0.99800003 22\n"
325  "-0.16635144 0.3699457 0.86900002 22\n"
326  "-0.33879143 0.36143145 0.84900004 22\n"
327  "-0.35055432 0.36853144 0.85800004 22\n"
328  "-0.39932001 0.38058859 0.89400005 22\n"
329  );
330 
331  DP pointCloud = IO::loadPCD(is);
332 
333  // Confirm sizes and dimensions
334  EXPECT_TRUE(pointCloud.features.cols() == 18);
335  EXPECT_TRUE(pointCloud.features.rows() == 4);
336  EXPECT_TRUE(pointCloud.descriptors.cols() == 18);
337  EXPECT_TRUE(pointCloud.descriptors.rows() == 1);
338 
339  // Random value check
340  EXPECT_NEAR(pointCloud.features(0, 0), 0.449121, 0.0000001);
341  EXPECT_NEAR(pointCloud.features(2, 2), 1.149, 0.0000001);
342  EXPECT_NEAR(pointCloud.descriptors(0, 10), 22, 0.0000001);
343 
344 }
345 
347 {
348 
349 public:
350  virtual void SetUp()
351  {
352  nbPts = 10;
353  addRandomFeature("x", 1);
354  addRandomFeature("y", 1);
355  addRandomFeature("z", 1);
356  ptCloud.addFeature("pad", PM::Matrix::Ones(1, nbPts));
357 
358  addRandomDescriptor("normals",3);
359  addRandomDescriptor("eigValues",3);
360  addRandomDescriptor("eigVectors",9);
361  addRandomDescriptor("color",4);
362  }
363 
364  void addRandomFeature(const string& featureName, const int rows)
365  {
366  ptCloud.addFeature(featureName,PM::Matrix::Random(rows, nbPts));
367  }
368 
369  void addRandomDescriptor(const string& descriptorName, const int rows)
370  {
371  ptCloud.addDescriptor(descriptorName, PM::Matrix::Random(rows, nbPts));
372  }
373 
374  virtual void loadSaveTest(const string& testFileName, bool plyFormat = false, const int nbPts = 10, bool binary = false, unsigned precision=12)
375  {
376  this->testFileName = testFileName;
377 
378  if (plyFormat || binary) {
379  // make sure random values generated for colors are within ply format range
380  int pointCount(ptCloud.features.cols());
381  int descRows(ptCloud.descriptors.rows());
382  bool datawithColor = ptCloud.descriptorExists("color");
383  int colorStartingRow = ptCloud.getDescriptorStartingRow("color");
384  int colorEndRow = colorStartingRow + ptCloud.getDescriptorDimension("color");
385  for (int p = 0; p < pointCount; ++p)
386  {
387  for (int d = 0; d < descRows; ++d)
388  {
389  if (datawithColor && d >= colorStartingRow && d < colorEndRow) {
390  if (ptCloud.descriptors(d, p) < 0) { ptCloud.descriptors.coeffRef(d, p) = -(ptCloud.descriptors(d, p)); }
391  ptCloud.descriptors.coeffRef(d, p) = (static_cast<unsigned>(ptCloud.descriptors(d, p) * 255.0)) / 255.0;
392  }
393  }
394  }
395  }
396 
397  ptCloud.save(testFileName, binary, precision);
398 
399  ptCloudFromFile = DP::load(testFileName);
400 
401  EXPECT_TRUE(ptCloudFromFile.features.cols() == ptCloud.features.cols());
402  EXPECT_TRUE(ptCloudFromFile.descriptorExists("normals",3));
403  EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("normals").isApprox(ptCloud.getDescriptorViewByName("normals")));
404  EXPECT_TRUE(ptCloudFromFile.descriptorExists("eigValues",3));
405  EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("eigValues").isApprox(ptCloud.getDescriptorViewByName("eigValues")));
406  EXPECT_TRUE(ptCloudFromFile.descriptorExists("eigVectors",9));
407  EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("eigVectors").isApprox(ptCloud.getDescriptorViewByName("eigVectors")));
408  EXPECT_TRUE(ptCloudFromFile.descriptorExists("color",4));
409  if (plyFormat || binary) {
410  EXPECT_TRUE(((ptCloudFromFile.getDescriptorViewByName("color") * 255.0)).isApprox((ptCloud.getDescriptorViewByName("color") * 255.0), 1.0));
411  } else {
412  EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("color").isApprox(ptCloud.getDescriptorViewByName("color")));
413  }
414 
415  EXPECT_TRUE(ptCloudFromFile.features.isApprox(ptCloud.features));
416 
417  }
418 
419  virtual void TearDown()
420  {
421  EXPECT_TRUE(boost::filesystem::remove(boost::filesystem::path(testFileName)));
422  }
423 
424 
425 protected:
426  int nbPts;
430  string testFileName;
431 
432 };
433 
435 {
436  ptCloud.addDescriptor("genericScalar", PM::Matrix::Random(1, nbPts));
437  ptCloud.addDescriptor("genericVector", PM::Matrix::Random(3, nbPts));
438  ptCloud.addTime("genericTime", PM::Int64Matrix::Random(1, nbPts));
439 
440  loadSaveTest(dataPath + "unit_test.vtk");
441 
442  EXPECT_TRUE(ptCloudFromFile.descriptorExists("genericScalar",1));
443  EXPECT_TRUE(ptCloudFromFile.descriptorExists("genericVector",3));
444  EXPECT_TRUE(ptCloudFromFile.timeExists("genericTime",1));
445 
446 }
447 
449 {
450  ptCloud.addDescriptor("genericScalar", PM::Matrix::Random(1, nbPts));
451  ptCloud.addDescriptor("genericVector", PM::Matrix::Random(3, nbPts));
452  ptCloud.addTime("genericTime", PM::Int64Matrix::Random(1, nbPts));
453 
454  loadSaveTest(dataPath + "unit_test.bin.vtk", false, 10, true);
455 
456  EXPECT_TRUE(ptCloudFromFile.descriptorExists("genericScalar",1));
457  EXPECT_TRUE(ptCloudFromFile.descriptorExists("genericVector",3));
458  EXPECT_TRUE(ptCloudFromFile.timeExists("genericTime",1));
459 }
460 
462 {
463  loadSaveTest(dataPath + "unit_test.ply", true);
464 }
465 
467 {
468  loadSaveTest(dataPath + "unit_test.pcd");
469 }
470 
472 {
473  loadSaveTest(dataPath + "unit_test.csv");
474 }
PointMatcherIO
IO Functions and classes that are dependant on scalar type are defined in this templatized class.
Definition: IO.h:43
IOLoadSaveTest::loadSaveTest
virtual void loadSaveTest(const string &testFileName, bool plyFormat=false, const int nbPts=10, bool binary=false, unsigned precision=12)
Definition: utest/ui/IO.cpp:374
PointMatcher::DataPoints::getNbGroupedDescriptors
unsigned getNbGroupedDescriptors() const
Return the number of grouped descriptors (e.g., normals can have 3 components but would count as only...
Definition: pointmatcher/DataPoints.cpp:180
IOLoadSaveTest::featureLabels
DP::Labels featureLabels
Definition: utest/ui/IO.cpp:427
IOLoadSaveTest::addRandomDescriptor
void addRandomDescriptor(const string &descriptorName, const int rows)
Definition: utest/ui/IO.cpp:369
PointMatcher::DataPoints::getEuclideanDim
unsigned getEuclideanDim() const
Return the dimension of the point cloud.
Definition: pointmatcher/DataPoints.cpp:165
PointMatcher::DataPoints::Labels
A vector of Label.
Definition: PointMatcher.h:229
EXPECT_NEAR
#define EXPECT_NEAR(val1, val2, abs_error)
Definition: gtest.h:19868
PointMatcher::DataPoints::descriptorExists
bool descriptorExists(const std::string &name) const
Look if a descriptor with a given name exist.
Definition: pointmatcher/DataPoints.cpp:583
DataPointsFilters
PM::DataPointsFilters DataPointsFilters
Definition: pypoint_matcher_helper.h:23
align_sequence.icp
icp
Definition: align_sequence.py:40
testing::Test
Definition: gtest.h:17760
TEST_F
TEST_F(IOLoadSaveTest, VTK)
Definition: utest/ui/IO.cpp:434
PointMatcher::DataPoints::getTimeDim
unsigned getTimeDim() const
Return the total number of times.
Definition: pointmatcher/DataPoints.cpp:194
PointMatcher::DataPoints
A point cloud.
Definition: PointMatcher.h:207
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: gtest.h:19327
PointMatcherSupport::InvalidModuleType
An exception thrown when one tries to use a module type that does not exist.
Definition: PointMatcher.h:83
TEST
TEST(IOTest, loadYaml)
Definition: utest/ui/IO.cpp:10
EXPECT_EQ
#define EXPECT_EQ(expected, actual)
Definition: gtest.h:19747
EXPECT_NO_THROW
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:19313
IOLoadSaveTest::addRandomFeature
void addRandomFeature(const string &featureName, const int rows)
Definition: utest/ui/IO.cpp:364
IOLoadSaveTest::ptCloud
DP ptCloud
Definition: utest/ui/IO.cpp:428
PointMatcher::DataPoints::descriptors
Matrix descriptors
descriptors of points in the cloud, might be empty
Definition: PointMatcher.h:333
ICP
PM::ICP ICP
Definition: pypoint_matcher_helper.h:33
PointMatcherSupport::Parametrizable::InvalidParameter
An exception thrown when one tries to fetch the value of an unexisting parameter.
Definition: Parametrizable.h:144
PointMatcher::DataPoints::getNbPoints
unsigned getNbPoints() const
Return the number of points contained in the point cloud.
Definition: pointmatcher/DataPoints.cpp:158
dataPath
std::string dataPath
Definition: utest.cpp:43
PointMatcher::DataPoints::features
Matrix features
features of points in the cloud
Definition: PointMatcher.h:331
IOLoadSaveTest::nbPts
int nbPts
Definition: utest/ui/IO.cpp:426
PointMatcher::DataPoints::times
Int64Matrix times
time associated to each points, might be empty
Definition: PointMatcher.h:335
IOLoadSaveTest::TearDown
virtual void TearDown()
Definition: utest/ui/IO.cpp:419
std
icp
Definition: icp.py:1
PointMatcher::DataPoints::getDescriptorDim
unsigned getDescriptorDim() const
Return the total number of descriptors.
Definition: pointmatcher/DataPoints.cpp:187
EXPECT_THROW
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:19311
IOLoadSaveTest::SetUp
virtual void SetUp()
Definition: utest/ui/IO.cpp:350
IOLoadSaveTest
Definition: utest/ui/IO.cpp:346
IOLoadSaveTest::ptCloudFromFile
DP ptCloudFromFile
Definition: utest/ui/IO.cpp:429
PointMatcherSupport
Functions and classes that are not dependant on scalar type are defined in this namespace.
Definition: Bibliography.cpp:45
PointMatcher::DataPoints::load
static DataPoints load(const std::string &fileName)
Load a point cloud from a file, determine format from extension.
Definition: pointmatcher/IO.cpp:375
IOLoadSaveTest::testFileName
string testFileName
Definition: utest/ui/IO.cpp:430


libpointmatcher
Author(s):
autogenerated on Mon Jul 1 2024 02:22:43