utest.cpp
Go to the documentation of this file.
00001 // kate: replace-tabs off; indent-width 4; indent-mode normal
00002 // vim: ts=4:sw=4:noexpandtab
00003 /*
00004 
00005 Copyright (c) 2010--2012,
00006 François Pomerleau and Stephane Magnenat, ASL, ETHZ, Switzerland
00007 You can contact the authors at <f dot pomerleau at gmail dot com> and
00008 <stephane at magnenat dot net>
00009 
00010 All rights reserved.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014     * Redistributions of source code must retain the above copyright
00015       notice, this list of conditions and the following disclaimer.
00016     * Redistributions in binary form must reproduce the above copyright
00017       notice, this list of conditions and the following disclaimer in the
00018       documentation and/or other materials provided with the distribution.
00019     * Neither the name of the <organization> nor the
00020       names of its contributors may be used to endorse or promote products
00021       derived from this software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00026 DISCLAIMED. IN NO EVENT SHALL ETH-ASL BE LIABLE FOR ANY
00027 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00030 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00031 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "pointmatcher/PointMatcher.h"
00037 #include "../contrib/gtest/gtest.h"
00038 
00039 #include <string>
00040 
00041 #include <fstream>
00042 
00043 #include "boost/filesystem.hpp"
00044 #include "boost/filesystem/path.hpp"
00045 #include "boost/filesystem/operations.hpp"
00046 
00047 using namespace std;
00048 using namespace PointMatcherSupport;
00049 using boost::assign::map_list_of;
00050 
00051 // TODO: avoid global by using testing::Environment
00052 // TODO: split the test into different cpp files:
00053 // - ut_DataPoints.cpp
00054 // - ut_IO.cpp
00055 // - ut_Icp.cpp
00056 // - ut_DataFilters.cpp
00057 // - ut_Matchers.cpp
00058 // - ut_Outliers.cpp
00059 // - ut_ErrorMinimizers.cpp
00060 // - ut_Transmations.cpp (checker and parameter)
00061 // - ut_
00062 typedef PointMatcher<float> PM;
00063 typedef PM::DataPoints DP;
00064 
00065 std::string dataPath;
00066 
00067 DP ref2D;
00068 DP data2D;
00069 DP ref3D;
00070 DP data3D;
00071 PM::TransformationParameters validT2d;
00072 PM::TransformationParameters validT3d;
00073 
00074 //---------------------------
00075 // Test ICP with all existing filters.
00076 
00077 // Algorithm:
00078 // 1. Iterate over all yaml files in
00079 //    libpointmatcher/examples/data/icp_data, each file tests ICP
00080 //    with one or more filters.
00081 // 2. Run ICP with the given yaml file. The filters in the yaml
00082 //    file are applied along the way.
00083 // 3. Write the obtained ICP transform to disk, to the same directory,
00084 //    with file extension .cur_trans (for easy future comparisons).
00085 // 4. Load the reference (known as correct) ICP transform from disk,
00086 //    from the same directory, with file extension .ref_trans.
00087 // 5. See if the current and reference transforms are equal.
00088 
00089 // To update an existing test or add a new test, simply add/modify
00090 // the desired yaml file, run the tests (they may fail this time), then
00091 // copy the (just written) desired current transform file on top of the
00092 // corresponding reference transform file. Run the tests again. This
00093 // time they will succeed.
00094 //---------------------------
00095 
00096 TEST(icpTest, icpTest)
00097 {
00098         DP ref  = DP::load(dataPath + "cloud.00000.vtk");
00099         DP data = DP::load(dataPath + "cloud.00001.vtk");
00100 
00101         namespace fs = boost::filesystem;
00102         fs::path config_dir(dataPath + "icp_data");
00103         EXPECT_TRUE( fs::exists(config_dir) && fs::is_directory(config_dir) );
00104 
00105         fs::directory_iterator end_iter;
00106         for( fs::directory_iterator d(config_dir); d != end_iter; ++d)
00107         {
00108                 if (!fs::is_regular_file(d->status()) ) continue;
00109 
00110                 // Load config file, and form ICP object
00111                 PM::ICP icp;
00112                 std::string config_file = d->path().string();
00113                 if (fs::extension(config_file) != ".yaml") continue;
00114                 std::ifstream ifs(config_file.c_str());
00115                 EXPECT_NO_THROW(icp.loadFromYaml(ifs)) << "This error was caused by the test file:" << endl << "   " << config_file;
00116 
00117                 // Compute current ICP transform
00118                 PM::TransformationParameters curT = icp(data, ref);
00119 
00120                 // Write current transform to disk (to easily compare it
00121                 // with reference transform offline)
00122                 fs::path cur_file = d->path();
00123                 cur_file.replace_extension(".cur_trans");
00124                 //std::cout << "Writing: " << cur_file << std::endl;
00125                 std::ofstream otfs(cur_file.c_str());
00126                 otfs.precision(16);
00127                 otfs << curT;
00128                 otfs.close();
00129                 
00130                 // Load reference transform
00131                 fs::path ref_file = d->path();
00132                 ref_file.replace_extension(".ref_trans");
00133                 PM::TransformationParameters refT = 0*curT;
00134                 //std::cout << "Reading: " << ref_file << std::endl;
00135                 std::ifstream itfs(ref_file.c_str());
00136                 for (int row = 0; row < refT.cols(); row++)
00137                 {
00138                         for (int col = 0; col < refT.cols(); col++)
00139                         {
00140                                 itfs >>refT(row, col);
00141                         }
00142                 }
00143 
00144                 // Dump the reference transform and current one
00145                 //std::cout.precision(17);
00146                 //std::cout << "refT:\n" << refT << std::endl;
00147                 //std::cout << "curT:\n" << curT << std::endl;
00148 
00149                 // Tolerance for change in rotation and translation
00150                 double rotTol = 0.1, transTol = 0.1;
00151 
00152                 // Find how much the reference rotation and translation
00153                 // differ from the current values.
00154                 PM::TransformationParameters refRot   = refT.block(0, 0, 3, 3);
00155                 PM::TransformationParameters refTrans = refT.block(0, 3, 3, 1);
00156                 PM::TransformationParameters curRot   = curT.block(0, 0, 3, 3);
00157                 PM::TransformationParameters curTrans = curT.block(0, 3, 3, 1);
00158                 PM::TransformationParameters rotErrMat = refRot*(curRot.transpose())
00159                   - PM::TransformationParameters::Identity(3, 3);
00160                 PM::TransformationParameters transErrMat = refTrans - curTrans;
00161                 double rotErr = rotErrMat.array().abs().sum();
00162                 double transErr = transErrMat.array().abs().sum();
00163 
00164                 //std::cout << "Rotation error:    " << rotErr   << std::endl;
00165                 //std::cout << "Translation error: " << transErr << std::endl;
00166                 
00167                 EXPECT_LT(rotErr,   rotTol) << "This error was caused by the test file:" << endl << "   " << config_file;
00168                 EXPECT_LT(transErr, transTol) << "This error was caused by the test file:" <<  endl << "   " << config_file;
00169         }
00170 }
00171 
00172 //---------------------------
00173 // Point-cloud structures
00174 //---------------------------
00175 
00176 TEST(PointCloudTest, CopyConstructor2D)
00177 {
00178         const DP ref2DCopy(ref2D);
00179         EXPECT_TRUE(ref2DCopy.features == ref2D.features);
00180         EXPECT_TRUE(ref2DCopy.featureLabels == ref2D.featureLabels);
00181         EXPECT_TRUE(ref2DCopy.descriptors == ref2D.descriptors);
00182         EXPECT_TRUE(ref2DCopy.descriptorLabels == ref2D.descriptorLabels);
00183         EXPECT_TRUE(ref2DCopy == ref2D);
00184 }
00185 
00186 TEST(PointCloudTest, CopyConstructor3D)
00187 {
00188         const DP ref3DCopy(ref3D);
00189         EXPECT_TRUE(ref3DCopy.features == ref3D.features);
00190         EXPECT_TRUE(ref3DCopy.featureLabels == ref3D.featureLabels);
00191         EXPECT_TRUE(ref3DCopy.descriptors == ref3D.descriptors);
00192         EXPECT_TRUE(ref3DCopy.descriptorLabels == ref3D.descriptorLabels);
00193         EXPECT_TRUE(ref3DCopy == ref3D);
00194 }
00195 
00196 TEST(PointCloudTest, FeatureConstructor2D)
00197 {
00198         const DP ref2DCopy(ref2D.features, ref2D.featureLabels);
00199         EXPECT_TRUE(ref2DCopy.features == ref2D.features);
00200         EXPECT_TRUE(ref2DCopy.featureLabels == ref2D.featureLabels);
00201         EXPECT_TRUE(ref2DCopy == ref2D);
00202         EXPECT_TRUE(ref2DCopy.descriptors.rows() == 0);
00203         EXPECT_TRUE(ref2DCopy.descriptors.cols() == 0);
00204 }
00205 
00206 TEST(PointCloudTest, FeatureConstructor3D)
00207 {
00208         const DP ref3DCopy(ref3D.features, ref3D.featureLabels);
00209         EXPECT_TRUE(ref3DCopy.features == ref3D.features);
00210         EXPECT_TRUE(ref3DCopy.featureLabels == ref3D.featureLabels);
00211         EXPECT_TRUE(ref3DCopy == ref3D);
00212         EXPECT_TRUE(ref3DCopy.descriptors.rows() == 0);
00213         EXPECT_TRUE(ref3DCopy.descriptors.cols() == 0);
00214 }
00215 
00216 TEST(PointCloudTest, ConcatenateFeatures2D)
00217 {
00218         const int leftPoints(ref2D.features.cols() / 2);
00219         const int rightPoints(ref2D.features.cols() - leftPoints);
00220         DP lefts(
00221                 ref2D.features.leftCols(leftPoints),
00222                 ref2D.featureLabels
00223         );
00224         DP rights(
00225                 ref2D.features.rightCols(rightPoints),
00226                 ref2D.featureLabels
00227         );
00228         lefts.concatenate(rights);
00229         EXPECT_TRUE(lefts == ref2D);
00230 }
00231 
00232 TEST(PointCloudTest, ConcatenateFeatures3D)
00233 {
00234         const int leftPoints(ref3D.features.cols() / 2);
00235         const int rightPoints(ref3D.features.cols() - leftPoints);
00236         DP lefts(
00237                 ref3D.features.leftCols(leftPoints),
00238                 ref3D.featureLabels
00239         );
00240         DP rights(
00241                 ref3D.features.rightCols(rightPoints),
00242                 ref3D.featureLabels
00243         );
00244         lefts.concatenate(rights);
00245         EXPECT_TRUE(lefts == ref3D);
00246 }
00247 
00248 TEST(PointCloudTest, ConcatenateDescSame)
00249 {
00250         typedef DP::Label Label;
00251         typedef DP::Labels Labels;
00252         
00253         const int leftPoints(ref2D.features.cols() / 2);
00254         const int rightPoints(ref2D.features.cols() - leftPoints);
00255         DP lefts(
00256                 ref2D.features.leftCols(leftPoints),
00257                 ref2D.featureLabels,
00258                 PM::Matrix::Random(5, leftPoints),
00259                 Labels(Label("Desc5D", 5))
00260         );
00261         DP rights(
00262                 ref2D.features.rightCols(rightPoints),
00263                 ref2D.featureLabels,
00264                 PM::Matrix::Random(5, rightPoints),
00265                 Labels(Label("Desc5D", 5))
00266         );
00267         lefts.concatenate(rights);
00268         EXPECT_TRUE(lefts.descriptors.rows() == 5);
00269         EXPECT_TRUE(lefts.descriptors.cols() == lefts.features.cols());
00270 }
00271 
00272 TEST(PointCloudTest, ConcatenateDescSame2)
00273 {
00274         typedef DP::Label Label;
00275         typedef DP::Labels Labels;
00276         
00277         DP ref3DCopy(ref3D.features, ref3D.featureLabels);
00278         ref3DCopy.descriptorLabels.push_back(Label("Desc5D", 5));
00279         ref3DCopy.descriptors = PM::Matrix::Random(5, ref3DCopy.features.cols());
00280         
00281         const int leftPoints(ref3DCopy.features.cols() / 2);
00282         const int rightPoints(ref3DCopy.features.cols() - leftPoints);
00283         DP lefts(
00284                 ref3DCopy.features.leftCols(leftPoints),
00285                 ref3DCopy.featureLabels,
00286                 ref3DCopy.descriptors.leftCols(leftPoints),
00287                 ref3DCopy.descriptorLabels
00288         );
00289         DP rights(
00290                 ref3DCopy.features.rightCols(rightPoints),
00291                 ref3DCopy.featureLabels,
00292                 ref3DCopy.descriptors.rightCols(rightPoints),
00293                 ref3DCopy.descriptorLabels
00294         );
00295         lefts.concatenate(rights);
00296         EXPECT_TRUE(lefts == ref3DCopy);
00297 }
00298 
00299 TEST(PointCloudTest, ConcatenateDescDiffName)
00300 {
00301         typedef DP::Label Label;
00302         typedef DP::Labels Labels;
00303         
00304         const int leftPoints(ref2D.features.cols() / 2);
00305         const int rightPoints(ref2D.features.cols() - leftPoints);
00306         DP lefts(
00307                 ref2D.features.leftCols(leftPoints),
00308                 ref2D.featureLabels,
00309                 PM::Matrix::Random(5, leftPoints),
00310                 Labels(Label("MyDesc5D", 5))
00311         );
00312         DP rights(
00313                 ref2D.features.rightCols(rightPoints),
00314                 ref2D.featureLabels,
00315                 PM::Matrix::Random(5, rightPoints),
00316                 Labels(Label("YourDesc5D", 5))
00317         );
00318         lefts.concatenate(rights);
00319         EXPECT_TRUE(lefts.descriptors.rows() == 0);
00320         EXPECT_TRUE(lefts.descriptors.cols() == 0);
00321 }
00322 
00323 TEST(PointCloudTest, ConcatenateDescDiffSize)
00324 {
00325         typedef DP::Label Label;
00326         typedef DP::Labels Labels;
00327         
00328         const int leftPoints(ref2D.features.cols() / 2);
00329         const int rightPoints(ref2D.features.cols() - leftPoints);
00330         DP lefts(
00331                 ref2D.features.leftCols(leftPoints),
00332                 ref2D.featureLabels,
00333                 PM::Matrix::Random(3, leftPoints),
00334                 Labels(Label("DescND", 3))
00335         );
00336         DP rights(
00337                 ref2D.features.rightCols(rightPoints),
00338                 ref2D.featureLabels,
00339                 PM::Matrix::Random(5, rightPoints),
00340                 Labels(Label("DescND", 5))
00341         );
00342         EXPECT_THROW(lefts.concatenate(rights), DP::InvalidField);
00343 }
00344 
00345 //---------------------------
00346 // Tests for IO
00347 //---------------------------
00348 
00349 TEST(IOTest, loadYaml)
00350 {
00351 
00352         // Test loading configuration files for data filters
00353         std::ifstream ifs0((dataPath + "default-convert.yaml").c_str());
00354         EXPECT_NO_THROW(PM::DataPointsFilters filters(ifs0));
00355 
00356         // Test loading configuration files for ICP
00357         PM::ICP icp;
00358 
00359         std::ifstream ifs1((dataPath + "default.yaml").c_str());
00360         EXPECT_NO_THROW(icp.loadFromYaml(ifs1));
00361 
00362         std::ifstream ifs2((dataPath + "unit_tests/badIcpConfig_InvalidParameter.yaml").c_str());
00363         EXPECT_THROW(icp.loadFromYaml(ifs2), PointMatcherSupport::Parametrizable::InvalidParameter);
00364         
00365         std::ifstream ifs3((dataPath + "unit_tests/badIcpConfig_InvalidModuleType.yaml").c_str());
00366         EXPECT_THROW(icp.loadFromYaml(ifs3), PointMatcherSupport::InvalidModuleType);
00367 }
00368 
00369 class IOLoadSaveTest : public testing::Test
00370 {
00371 
00372 public:
00373         virtual void SetUp()
00374         {
00375                 nbPts = 10;
00376                 addRandomFeature("x", 1);
00377                 addRandomFeature("y", 1);
00378                 addRandomFeature("z", 1);
00379                 ptCloud.addFeature("pad", PM::Matrix::Ones(1, nbPts));
00380 
00381                 addRandomDescriptor("normals",3);
00382                 addRandomDescriptor("eigValues",3);
00383                 addRandomDescriptor("eigVectors",9);
00384                 addRandomDescriptor("color",4);
00385         }
00386 
00387         void addRandomFeature(const string& featureName, const int rows)
00388         {
00389                 ptCloud.addFeature(featureName,PM::Matrix::Random(rows, nbPts));
00390         }
00391 
00392         void addRandomDescriptor(const string& descriptorName, const int rows)
00393         {
00394                 ptCloud.addDescriptor(descriptorName, PM::Matrix::Random(rows, nbPts));
00395         }
00396 
00397         virtual void loadSaveTest(const string& testFileName, const int nbPts = 10)
00398         {
00399                 this->testFileName = testFileName;
00400                 ptCloud.save(testFileName);
00401 
00402                 ptCloudFromFile = DP::load(testFileName);
00403 
00404                 EXPECT_TRUE(ptCloudFromFile.features.cols() == ptCloud.features.cols());
00405                 EXPECT_TRUE(ptCloudFromFile.descriptorExists("normals",3));
00406                 EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("normals").isApprox(ptCloud.getDescriptorViewByName("normals")));
00407                 EXPECT_TRUE(ptCloudFromFile.descriptorExists("eigValues",3));
00408                 EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("eigValues").isApprox(ptCloud.getDescriptorViewByName("eigValues")));
00409                 EXPECT_TRUE(ptCloudFromFile.descriptorExists("eigVectors",9));
00410                 EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("eigVectors").isApprox(ptCloud.getDescriptorViewByName("eigVectors")));
00411                 EXPECT_TRUE(ptCloudFromFile.descriptorExists("color",4));
00412                 EXPECT_TRUE(ptCloudFromFile.getDescriptorViewByName("color").isApprox(ptCloud.getDescriptorViewByName("color")));
00413 
00414                 EXPECT_TRUE(ptCloudFromFile.features.isApprox(ptCloud.features));
00415 
00416         }
00417 
00418         virtual void TearDown()
00419         {
00420                 EXPECT_TRUE(boost::filesystem::remove(boost::filesystem::path(testFileName)));
00421         }
00422 
00423 
00424 protected:
00425         int nbPts;
00426         DP::Labels featureLabels;
00427         DP ptCloud;
00428         DP ptCloudFromFile;
00429         string testFileName;
00430 
00431 };
00432 
00433 TEST_F(IOLoadSaveTest, VTK)
00434 {
00435         ptCloud.addDescriptor("genericScalar", PM::Matrix::Random(1, nbPts));
00436         ptCloud.addDescriptor("genericVector", PM::Matrix::Random(3, nbPts));
00437 
00438         loadSaveTest("unit_test.vtk");
00439 
00440         EXPECT_TRUE(ptCloudFromFile.descriptorExists("genericScalar",1));
00441         EXPECT_TRUE(ptCloudFromFile.descriptorExists("genericVector",3));
00442 
00443 }
00444 
00445 TEST_F(IOLoadSaveTest, PLY)
00446 {
00447         loadSaveTest("unit_test.ply");
00448 }
00449 
00450 TEST_F(IOLoadSaveTest, PCD)
00451 {
00452         loadSaveTest("unit_test.pcd");
00453 }
00454 
00455 TEST_F(IOLoadSaveTest, CSV)
00456 {
00457         loadSaveTest("unit_test.csv");
00458 }
00459 
00460 
00461 
00462 //---------------------------
00463 // Base for ICP tests
00464 //---------------------------
00465 
00466 class IcpHelper: public testing::Test
00467 {
00468 public:
00469         
00470         PM::ICP icp;
00471         
00472         PM::Parameters params;
00473 
00474         virtual void dumpVTK()
00475         {
00476                 // Make available a VTK inspector for manual inspection
00477                 icp.inspector.reset(
00478                         PM::get().InspectorRegistrar.create(
00479                                 "VTKFileInspector", 
00480                                 boost::assign::map_list_of
00481                                         ("baseFileName","./unitTest")
00482                         )
00483                 );
00484         }
00485         
00486         void validate2dTransformation()
00487         {
00488                 const PM::TransformationParameters testT = icp(data2D, ref2D);
00489                 const int dim = validT2d.cols();
00490 
00491                 const BOOST_AUTO(validTrans, validT2d.block(0, dim-1, dim-1, 1).norm());
00492                 const BOOST_AUTO(testTrans, testT.block(0, dim-1, dim-1, 1).norm());
00493         
00494                 const BOOST_AUTO(validAngle, acos(validT2d(0,0)));
00495                 const BOOST_AUTO(testAngle, acos(testT(0,0)));
00496                 
00497                 EXPECT_NEAR(validTrans, testTrans, 0.05);
00498                 EXPECT_NEAR(validAngle, testAngle, 0.05);
00499         }
00500 
00501         void validate3dTransformation()
00502         {
00503                 //dumpVTK();
00504 
00505                 const PM::TransformationParameters testT = icp(data3D, ref3D);
00506                 const int dim = validT2d.cols();
00507 
00508                 const BOOST_AUTO(validTrans, validT3d.block(0, dim-1, dim-1, 1).norm());
00509                 const BOOST_AUTO(testTrans, testT.block(0, dim-1, dim-1, 1).norm());
00510         
00511                 const BOOST_AUTO(testRotation, Eigen::Quaternion<float>(Eigen::Matrix<float,3,3>(testT.topLeftCorner(3,3))));
00512                 const BOOST_AUTO(validRotation, Eigen::Quaternion<float>(Eigen::Matrix<float,3,3>(validT3d.topLeftCorner(3,3))));
00513                 
00514                 const BOOST_AUTO(angleDist, validRotation.angularDistance(testRotation));
00515                 
00516                 //cout << testT << endl;
00517                 //cout << "angleDist: " << angleDist << endl;
00518                 //cout << "transDist: " << abs(validTrans-testTrans) << endl;
00519                 EXPECT_NEAR(validTrans, testTrans, 0.1);
00520                 EXPECT_NEAR(angleDist, 0.0, 0.1);
00521 
00522         }
00523 };
00524 
00525 // Utility classes
00526 class GenericTest: public IcpHelper
00527 {
00528 
00529 public:
00530 
00531         // Will be called for every tests
00532         virtual void SetUp()
00533         {
00534                 icp.setDefault();
00535                 // Uncomment for consol outputs
00536                 //setLogger(PM::get().LoggerRegistrar.create("FileLogger"));
00537         }
00538 
00539         // Will be called for every tests
00540         virtual void TearDown()
00541         {       
00542         }
00543 };
00544 
00545 
00546 //---------------------------
00547 // Generic tests
00548 //---------------------------
00549 
00550 TEST_F(GenericTest, ICP_default)
00551 {
00552         validate2dTransformation();
00553         validate3dTransformation();
00554 }
00555 
00556 //---------------------------
00557 // DataFilter modules
00558 //---------------------------
00559 
00560 // Utility classes
00561 class DataFilterTest: public IcpHelper
00562 {
00563 public:
00564         // Will be called for every tests
00565         virtual void SetUp()
00566         {
00567                 icp.setDefault();
00568                 // Uncomment for console outputs
00569                 //setLogger(PM::get().LoggerRegistrar.create("FileLogger"));
00570                 
00571                 // We'll test the filters on reading point cloud
00572                 icp.readingDataPointsFilters.clear();
00573         }
00574 
00575         // Will be called for every tests
00576         virtual void TearDown() {}
00577 
00578         void addFilter(string name, PM::Parameters params)
00579         {
00580                 PM::DataPointsFilter* testedDataPointFilter = 
00581                         PM::get().DataPointsFilterRegistrar.create(name, params);
00582         
00583                 icp.readingDataPointsFilters.push_back(testedDataPointFilter);
00584         }
00585         
00586         void addFilter(string name)
00587         {
00588                 PM::DataPointsFilter* testedDataPointFilter = 
00589                         PM::get().DataPointsFilterRegistrar.create(name);
00590                 
00591                 icp.readingDataPointsFilters.push_back(testedDataPointFilter);
00592         }
00593 };
00594 
00595 
00596 TEST_F(DataFilterTest, RemoveNaNDataPointsFilter)
00597 {
00598         // build test cloud
00599         DP ref2DCopy(ref2D);
00600         int goodCount(0);
00601         const float nan(std::numeric_limits<float>::quiet_NaN());
00602         for (int i(0); i < ref2DCopy.features.cols(); ++i)
00603         {
00604                 if (rand() % 3 == 0)
00605                 {
00606                         ref2DCopy.features(rand() % ref2DCopy.features.rows(), i) = nan;
00607                 }
00608                 else
00609                         ++goodCount;
00610         }
00611         
00612         // apply and checked
00613         addFilter("RemoveNaNDataPointsFilter");
00614         icp.readingDataPointsFilters.apply(ref2DCopy);
00615         EXPECT_TRUE(ref2DCopy.features.cols() == goodCount);
00616 }
00617 
00618 TEST_F(DataFilterTest, MaxDistDataPointsFilter)
00619 {
00620         // Max dist has been selected to not affect the points
00621         params = map_list_of<string,string>
00622                 ("dim","0")
00623                 ("maxDist", toParam(6.0))
00624         ;
00625         
00626         // Filter on x axis
00627         params["dim"] = "0";
00628         icp.readingDataPointsFilters.clear();
00629         addFilter("MaxDistDataPointsFilter", params);
00630         validate2dTransformation();
00631         validate3dTransformation();
00632         
00633         // Filter on y axis
00634         params["dim"] = "1";
00635         icp.readingDataPointsFilters.clear();
00636         addFilter("MaxDistDataPointsFilter", params);
00637         validate2dTransformation();
00638         validate3dTransformation();
00639         
00640         // Filter on z axis (not existing)
00641         params["dim"] = "2";
00642         icp.readingDataPointsFilters.clear();
00643         addFilter("MaxDistDataPointsFilter", params);
00644         EXPECT_ANY_THROW(validate2dTransformation());
00645         validate3dTransformation();
00646         
00647         // Filter on a radius
00648         params["dim"] = "-1";
00649         icp.readingDataPointsFilters.clear();
00650         addFilter("MaxDistDataPointsFilter", params);
00651         validate2dTransformation();
00652         validate3dTransformation();
00653         
00654         // Parameter outside valid range
00655         params["dim"] = "3";
00656         //TODO: specify the exception, move that to GenericTest
00657         EXPECT_ANY_THROW(addFilter("MaxDistDataPointsFilter", params));
00658         
00659 }
00660 
00661 TEST_F(DataFilterTest, MinDistDataPointsFilter)
00662 {
00663         // Min dist has been selected to not affect the points too much
00664         params = map_list_of<string,string>
00665                 ("dim","0")
00666                 ("minDist", toParam(0.05))
00667         ;
00668         
00669         // Filter on x axis
00670         params["dim"] = "0";
00671         icp.readingDataPointsFilters.clear();
00672         addFilter("MinDistDataPointsFilter", params);
00673         validate2dTransformation();
00674         validate3dTransformation();
00675         
00676         // Filter on y axis
00677         params["dim"] = "1";
00678         icp.readingDataPointsFilters.clear();
00679         addFilter("MinDistDataPointsFilter", params);
00680         validate2dTransformation();
00681         validate3dTransformation();
00682         
00683         //TODO: move that to specific 2D test
00684         // Filter on z axis (not existing)
00685         params["dim"] = "2";
00686         icp.readingDataPointsFilters.clear();
00687         addFilter("MinDistDataPointsFilter", params);
00688         EXPECT_ANY_THROW(validate2dTransformation());
00689         validate3dTransformation();
00690         
00691         // Filter on a radius
00692         params["dim"] = "-1";
00693         icp.readingDataPointsFilters.clear();
00694         addFilter("MinDistDataPointsFilter", params);
00695         validate2dTransformation();
00696         validate3dTransformation();
00697                 
00698 }
00699 
00700 TEST_F(DataFilterTest, MaxQuantileOnAxisDataPointsFilter)
00701 {
00702         // Ratio has been selected to not affect the points too much
00703         string ratio = "0.95";
00704         params = map_list_of<string,string>
00705                 ("dim","0")
00706                 ("ratio", ratio)
00707         ;
00708         
00709         // Filter on x axis
00710         params["dim"] = "0";
00711         icp.readingDataPointsFilters.clear();
00712         addFilter("MaxQuantileOnAxisDataPointsFilter", params);
00713         validate2dTransformation();
00714         validate3dTransformation();
00715         
00716         // Filter on y axis
00717         params["dim"] = "1";
00718         icp.readingDataPointsFilters.clear();
00719         addFilter("MaxQuantileOnAxisDataPointsFilter", params);
00720         validate2dTransformation();
00721         validate3dTransformation();
00722         
00723         // Filter on z axis (not existing)
00724         params["dim"] = "2";
00725         icp.readingDataPointsFilters.clear();
00726         addFilter("MaxQuantileOnAxisDataPointsFilter", params);
00727         EXPECT_ANY_THROW(validate2dTransformation());
00728         validate3dTransformation();
00729 }
00730 
00731 
00732 
00733 TEST_F(DataFilterTest, SurfaceNormalDataPointsFilter)
00734 {
00735         // This filter create descriptor, so parameters should'nt impact results
00736         params = map_list_of
00737                 ("knn", "5") 
00738                 ("epsilon", "0.1") 
00739                 ("keepNormals", "1")
00740                 ("keepDensities", "1")
00741                 ("keepEigenValues", "1")
00742                 ("keepEigenVectors", "1" )
00743                 ("keepMatchedIds" , "1" )
00744         ;
00745         // FIXME: the parameter keepMatchedIds seems to do nothing...
00746 
00747         addFilter("SurfaceNormalDataPointsFilter", params);
00748         validate2dTransformation();     
00749         validate3dTransformation();
00750 
00751         // TODO: standardize how filter are tested:
00752         // 1- impact on number of points
00753         // 2- impact on descriptors
00754         // 3- impact on ICP (that's what we test now)
00755 }
00756 
00757 TEST_F(DataFilterTest, MaxDensityDataPointsFilter)
00758 {
00759         // Ratio has been selected to not affect the points too much
00760         vector<double> ratio = list_of (100) (1000) (5000);
00761  
00762         for(unsigned i=0; i < ratio.size(); i++)
00763         {
00764                 icp.readingDataPointsFilters.clear();
00765                 params = map_list_of
00766                         ("knn", "5") 
00767                         ("epsilon", "0.1") 
00768                         ("keepNormals", "0")
00769                         ("keepDensities", "1")
00770                         ("keepEigenValues", "0")
00771                         ("keepEigenVectors", "0" )
00772                         ("keepMatchedIds" , "0" )
00773                 ;
00774 
00775                 addFilter("SurfaceNormalDataPointsFilter", params);
00776 
00777                 params = map_list_of ("maxDensity", toParam(ratio[i]));
00778                 addFilter("MaxDensityDataPointsFilter", params);
00779                 
00780                 // FIXME BUG: the density in 2D is not well computed
00781                 //validate2dTransformation();   
00782  
00783                 //double nbInitPts = data2D.features.cols();
00784                 //double nbRemainingPts = icp.getPrefilteredReadingPtsCount();
00785                 //EXPECT_TRUE(nbRemainingPts < nbInitPts);
00786                 
00787                 validate3dTransformation();
00788 
00789                 double nbInitPts = data3D.features.cols();
00790                 double nbRemainingPts = icp.getPrefilteredReadingPtsCount();
00791                 EXPECT_TRUE(nbRemainingPts < nbInitPts);
00792         }
00793 }
00794 
00795 TEST_F(DataFilterTest, SamplingSurfaceNormalDataPointsFilter)
00796 {
00797         // This filter create descriptor AND subsample
00798         params = map_list_of
00799                 ("knn", "5")
00800                 ("averageExistingDescriptors", "1")
00801                 ("keepNormals", "1")
00802                 ("keepDensities", "1")
00803                 ("keepEigenValues", "1")
00804                 ("keepEigenVectors", "1")
00805         ;
00806         
00807         addFilter("SamplingSurfaceNormalDataPointsFilter", params);
00808         validate2dTransformation();
00809         validate3dTransformation();
00810 
00811 }
00812 
00813 TEST_F(DataFilterTest, OrientNormalsDataPointsFilter)
00814 {
00815         // Used to create normal for reading point cloud
00816         PM::DataPointsFilter* extraDataPointFilter;
00817         extraDataPointFilter = PM::get().DataPointsFilterRegistrar.create(
00818                         "SurfaceNormalDataPointsFilter");
00819         icp.readingDataPointsFilters.push_back(extraDataPointFilter);
00820         addFilter("ObservationDirectionDataPointsFilter");
00821         addFilter("OrientNormalsDataPointsFilter", map_list_of
00822                 ("towardCenter", toParam(false))
00823         );
00824         validate2dTransformation();
00825         validate3dTransformation();
00826 }
00827 
00828 
00829 TEST_F(DataFilterTest, RandomSamplingDataPointsFilter)
00830 {
00831         vector<double> prob = list_of (0.80) (0.85) (0.90) (0.95);
00832         for(unsigned i=0; i<prob.size(); i++)
00833         {
00834                 // Try to avoid to low value for the reduction to avoid under sampling
00835                 params = map_list_of
00836                         ("prob", toParam(prob[i]))
00837                 ;
00838                 icp.readingDataPointsFilters.clear();
00839                 addFilter("RandomSamplingDataPointsFilter", params);
00840                 validate2dTransformation();
00841                 validate3dTransformation();
00842         }
00843 }
00844 
00845 TEST_F(DataFilterTest, FixStepSamplingDataPointsFilter)
00846 {
00847         vector<unsigned> steps = list_of (1) (2) (3);
00848         for(unsigned i=0; i<steps.size(); i++)
00849         {
00850                 // Try to avoid too low value for the reduction to avoid under sampling
00851                 params = map_list_of
00852                         ("startStep", toParam(steps[i]))
00853                 ;
00854                 icp.readingDataPointsFilters.clear();
00855                 addFilter("FixStepSamplingDataPointsFilter", params);
00856                 validate2dTransformation();
00857                 validate3dTransformation();
00858         }
00859 }
00860 
00861 TEST_F(DataFilterTest, VoxelGridDataPointsFilter)
00862 {
00863         vector<bool> useCentroid = list_of(false)(true);
00864         vector<bool> averageExistingDescriptors = list_of(false)(true);
00865         for (unsigned i = 0 ; i < useCentroid.size() ; i++) 
00866         {
00867                 for (unsigned j = 0; j < averageExistingDescriptors.size(); j++) 
00868                 {
00869                         params = map_list_of<string,string>
00870                                         ("vSizeX","0.02")
00871                                         ("vSizeY","0.02")
00872                                         ("vSizeZ","0.02")
00873                                         ("useCentroid",toParam(true))
00874                                         ("averageExistingDescriptors",toParam(true))
00875                         ;
00876                         icp.readingDataPointsFilters.clear();
00877                         addFilter("VoxelGridDataPointsFilter", params);
00878                         validate2dTransformation();
00879                 }
00880         }
00881 
00882         for (unsigned i = 0 ; i < useCentroid.size() ; i++)
00883         {
00884                 for (unsigned j = 0; j < averageExistingDescriptors.size(); j++)
00885                 {
00886                         params = map_list_of<string,string>
00887                         ("vSizeX","1")
00888                         ("vSizeY","1")
00889                         ("vSizeZ","1")
00890                         ("useCentroid",toParam(true))
00891                         ("averageExistingDescriptors",toParam(true));
00892                         icp.readingDataPointsFilters.clear();
00893                         addFilter("VoxelGridDataPointsFilter", params);
00894                         validate3dTransformation();
00895                 }
00896         }
00897 }
00898 
00899 //---------------------------
00900 // Matcher modules
00901 //---------------------------
00902 
00903 // Utility classes
00904 class MatcherTest: public IcpHelper
00905 {
00906 
00907 public:
00908 
00909         PM::Matcher* testedMatcher;
00910 
00911         // Will be called for every tests
00912         virtual void SetUp()
00913         {
00914                 icp.setDefault();
00915                 // Uncomment for consol outputs
00916                 //setLogger(PM::get().LoggerRegistrar.create("FileLogger"));
00917         }
00918 
00919         // Will be called for every tests
00920         virtual void TearDown(){}
00921 
00922         void addFilter(string name, PM::Parameters params)
00923         {
00924                 testedMatcher = 
00925                         PM::get().MatcherRegistrar.create(name, params);
00926                 icp.matcher.reset(testedMatcher);
00927         }
00928 
00929 };
00930 
00931 TEST_F(MatcherTest, KDTreeMatcher)
00932 {
00933         vector<unsigned> knn = list_of (1) (2) (3);
00934         vector<double> epsilon = list_of (0.0) (0.2);
00935         vector<double> maxDist = list_of (1.0) (0.5);
00936 
00937         for(unsigned i=0; i < knn.size(); i++)
00938         {
00939                 for(unsigned j=0; j < epsilon.size(); j++)
00940                 {
00941                         for(unsigned k=0; k < maxDist.size(); k++)
00942                         {
00943                                 params = map_list_of
00944                                         ("knn", toParam(knn[i])) // remove end parenthesis for bug
00945                                         ("epsilon", toParam(epsilon[j]))
00946                                         ("searchType", "1")
00947                                         ("maxDist", toParam(maxDist[k]))
00948                                 ;
00949                         
00950                                 addFilter("KDTreeMatcher", params);
00951                                 validate2dTransformation();
00952                                 validate3dTransformation();
00953                         }
00954                 }
00955         }
00956 }
00957 
00958 
00959 //---------------------------
00960 // Outlier modules
00961 //---------------------------
00962 
00963 // Utility classes
00964 class OutlierFilterTest: public IcpHelper
00965 {
00966 public:
00967         PM::OutlierFilter* testedOutlierFilter;
00968 
00969         // Will be called for every tests
00970         virtual void SetUp()
00971         {
00972                 icp.setDefault();
00973                 // Uncomment for consol outputs
00974                 //setLogger(PM::get().LoggerRegistrar.create("FileLogger"));
00975                 
00976                 icp.outlierFilters.clear();
00977         }
00978 
00979         // Will be called for every tests
00980         virtual void TearDown(){}
00981 
00982         void addFilter(string name, PM::Parameters params)
00983         {
00984                 testedOutlierFilter = 
00985                         PM::get().OutlierFilterRegistrar.create(name, params);
00986                 icp.outlierFilters.push_back(testedOutlierFilter);
00987         }
00988 
00989 };
00990 
00991 
00992 //No commun parameters were found for 2D and 3D, tests are splited
00993 TEST_F(OutlierFilterTest, MaxDistOutlierFilter2D)
00994 {
00995         addFilter("MaxDistOutlierFilter", map_list_of
00996                 ("maxDist", toParam(0.015))
00997         );
00998         validate2dTransformation();
00999 }
01000 
01001 TEST_F(OutlierFilterTest, MaxDistOutlierFilter3D)
01002 {
01003         addFilter("MaxDistOutlierFilter", map_list_of
01004                 ("maxDist", toParam(0.1))
01005         );
01006         validate3dTransformation();
01007 }
01008 
01009 //No commun parameters were found for 2D and 3D, tests are splited
01010 TEST_F(OutlierFilterTest, MinDistOutlierFilter2D)
01011 {
01012         // Since not sure how useful is that filter, we keep the 
01013         // MaxDistOutlierFilter with it
01014         PM::OutlierFilter* extraOutlierFilter;
01015         
01016         extraOutlierFilter = 
01017                 PM::get().OutlierFilterRegistrar.create(
01018                         "MaxDistOutlierFilter", map_list_of 
01019                                 ("maxDist", toParam(0.015))
01020                 )
01021         ;
01022         icp.outlierFilters.push_back(extraOutlierFilter);
01023         
01024         addFilter("MinDistOutlierFilter", map_list_of ("minDist", toParam(0.0002)) );
01025         
01026         validate2dTransformation();
01027 }
01028 
01029 TEST_F(OutlierFilterTest, MinDistOutlierFilter3D)
01030 {
01031         // Since not sure how useful is that filter, we keep the 
01032         // MaxDistOutlierFilter with it
01033         PM::OutlierFilter* extraOutlierFilter;
01034         
01035         extraOutlierFilter = 
01036                 PM::get().OutlierFilterRegistrar.create(
01037                         "MaxDistOutlierFilter", map_list_of 
01038                                 ("maxDist", toParam(0.1))
01039                 )
01040         ;
01041         icp.outlierFilters.push_back(extraOutlierFilter);
01042         
01043         addFilter("MinDistOutlierFilter", map_list_of ("minDist", toParam(0.0002)) );
01044         
01045         validate3dTransformation();
01046 }
01047 
01048 TEST_F(OutlierFilterTest, MedianDistOutlierFilter)
01049 {
01050         addFilter("MedianDistOutlierFilter", map_list_of ("factor", toParam(3.5)));
01051         validate2dTransformation();
01052         validate3dTransformation();
01053 }
01054 
01055 
01056 TEST_F(OutlierFilterTest, TrimmedDistOutlierFilter)
01057 {
01058         addFilter("TrimmedDistOutlierFilter", map_list_of ("ratio", toParam(0.85)) );
01059         validate2dTransformation();
01060         validate3dTransformation();
01061 }
01062 
01063 
01064 TEST_F(OutlierFilterTest, VarTrimmedDistOutlierFilter)
01065 {
01066         addFilter("VarTrimmedDistOutlierFilter", map_list_of
01067                 ("minRatio", toParam(0.60))
01068                 ("maxRatio", toParam(0.80))
01069                 ("lambda", toParam(0.9))
01070         );
01071         validate2dTransformation();
01072         validate3dTransformation();
01073 }
01074 
01075 //---------------------------
01076 // Error modules
01077 //---------------------------
01078 
01079 // Utility classes
01080 class ErrorMinimizerTest: public IcpHelper
01081 {
01082 public:
01083         PM::ErrorMinimizer* errorMin;
01084 
01085         // Will be called for every tests
01086         virtual void SetUp()
01087         {
01088                 icp.setDefault();
01089                 // Uncomment for consol outputs
01090                 //setLogger(PM::get().LoggerRegistrar.create("FileLogger"));
01091         }
01092 
01093         // Will be called for every tests
01094         virtual void TearDown(){}
01095 
01096         void addFilter(string name)
01097         {
01098                 errorMin = PM::get().ErrorMinimizerRegistrar.create(name);
01099                 icp.errorMinimizer.reset(errorMin);
01100         }
01101 };
01102 
01103 
01104 TEST_F(ErrorMinimizerTest, PointToPointErrorMinimizer)
01105 {
01106         addFilter("PointToPointErrorMinimizer");        
01107         validate2dTransformation();
01108         validate3dTransformation();
01109 }
01110 
01111 TEST_F(ErrorMinimizerTest, PointToPlaneErrorMinimizer)
01112 {
01113         addFilter("PointToPlaneErrorMinimizer");        
01114         validate2dTransformation();
01115         validate3dTransformation();
01116 }
01117 
01118 //---------------------------
01119 // Transformation Checker modules
01120 //---------------------------
01121 
01122 // Utility classes
01123 class TransformationCheckerTest: public IcpHelper
01124 {
01125 public:
01126         PM::TransformationChecker* transformCheck;
01127 
01128         // Will be called for every tests
01129         virtual void SetUp()
01130         {
01131                 icp.setDefault();
01132                 // Uncomment for consol outputs
01133                 //setLogger(PM::get().LoggerRegistrar.create("FileLogger"));
01134                 
01135                 icp.transformationCheckers.clear();
01136         }
01137 
01138         // Will be called for every tests
01139         virtual void TearDown(){}
01140 
01141         void addFilter(string name, PM::Parameters params)
01142         {
01143                 transformCheck = 
01144                         PM::get().TransformationCheckerRegistrar.create(name, params);
01145                 
01146                 icp.transformationCheckers.push_back(transformCheck);
01147         }
01148 };
01149 
01150 
01151 TEST_F(TransformationCheckerTest, CounterTransformationChecker)
01152 {
01153         addFilter("CounterTransformationChecker", map_list_of ("maxIterationCount", toParam(20)) );
01154         validate2dTransformation();
01155 }
01156 
01157 TEST_F(TransformationCheckerTest, DifferentialTransformationChecker)
01158 {
01159         addFilter("DifferentialTransformationChecker", map_list_of
01160                 ("minDiffRotErr", toParam(0.001))
01161                 ("minDiffTransErr", toParam(0.001))
01162                 ("smoothLength", toParam(4))
01163         );
01164         validate2dTransformation();
01165 }
01166 
01167 TEST_F(TransformationCheckerTest, BoundTransformationChecker)
01168 {
01169         // Since that transChecker is trigger when the distance is growing
01170         // and that we do not expect that to happen in the test dataset, we
01171         // keep the Counter to get out of the looop     
01172         PM::TransformationChecker* extraTransformCheck;
01173         
01174         extraTransformCheck = PM::get().TransformationCheckerRegistrar.create(
01175                 "CounterTransformationChecker"
01176         );
01177         icp.transformationCheckers.push_back(extraTransformCheck);
01178         
01179         addFilter("BoundTransformationChecker", map_list_of
01180                 ("maxRotationNorm", toParam(1.0))
01181                 ("maxTranslationNorm", toParam(1.0))
01182         );
01183         validate2dTransformation();
01184 }
01185 
01186 //---------------------------
01187 // Transformation
01188 //---------------------------
01189 TEST(Transformation, RigidTransformation)
01190 {
01191         PM::Transformation* rigidTrans;
01192         rigidTrans = PM::get().REG(Transformation).create("RigidTransformation");
01193 
01194         //-------------------------------------
01195         // Construct a 3D non-orthogonal matrix
01196         PM::Matrix T_3D = PM::Matrix::Identity(4,4);
01197         T_3D(0,0) = 2.3;
01198         T_3D(0,1) = 0.03;
01199 
01200         EXPECT_FALSE(rigidTrans->checkParameters(T_3D));
01201 
01202         EXPECT_THROW(rigidTrans->compute(data3D, T_3D), TransformationError);
01203 
01204         // Check stability over iterations
01205         for(int i = 0; i < 10; i++)
01206         {
01207                 T_3D = rigidTrans->correctParameters(T_3D);
01208                 EXPECT_TRUE(rigidTrans->checkParameters(T_3D));
01209         }
01210 
01211         //-------------------------------------
01212         // Construct a 2D non-orthogonal matrix
01213         PM::Matrix T_2D = PM::Matrix::Identity(3,3);
01214         T_2D(1,0) = 8.99;
01215         T_2D(0,1) = 4.03;
01216 
01217         EXPECT_FALSE(rigidTrans->checkParameters(T_2D));
01218 
01219         EXPECT_THROW(rigidTrans->compute(data2D, T_2D), TransformationError);
01220 
01221         // Check stability over iterations
01222         for(int i = 0; i < 10; i++)
01223         {
01224                 T_2D = rigidTrans->correctParameters(T_2D);
01225                 EXPECT_TRUE(rigidTrans->checkParameters(T_2D));
01226         }
01227 
01228 }
01229 
01230 //---------------------------
01231 // Inspectors
01232 //---------------------------
01233 TEST(Inspectors, PerformanceInspector)
01234 {
01235         PM::Inspector* performances =
01236                 PM::get().REG(Inspector).create(
01237                         "PerformanceInspector", map_list_of
01238                                 ("baseFileName", "/tmp/utest_performances")
01239                                 ("dumpPerfOnExit", "1")
01240                 )
01241         ;
01242         //TODO: we only test constructor here, check other things...
01243 }
01244 
01245 TEST(Inspectors, VTKFileInspector)
01246 {
01247         PM::Inspector* vtkFile = 
01248                 PM::get().REG(Inspector).create(
01249                         "VTKFileInspector", map_list_of
01250                                 ("baseFileName", "/tmp/utest_vtk")
01251                                 ("dumpPerfOnExit", "1")
01252                 )
01253         ;
01254         //TODO: we only test constructor here, check other things...
01255 }
01256 
01257 //---------------------------
01258 // Loggers
01259 //---------------------------
01260 
01261 //TODO: FileLogger
01262 //Log using std::stream.
01263 //- infoFileName (default: /dev/stdout) - name of the file to output infos to
01264 //- warningFileName (default: /dev/stderr) - name of the file to output warnings to
01265 //- displayLocation (default: 0) - display the location of message in source code
01266 TEST(Loggers, FileLogger)
01267 {
01268         string infoFileName = "utest_info";
01269         string warningFileName = "utest_warn";
01270 
01271         Logger* fileLog = 
01272                 PM::get().REG(Logger).create(
01273                         "FileLogger", map_list_of
01274                                 ("infoFileName", infoFileName)
01275                                 ("warningFileName", warningFileName)
01276                                 ("displayLocation", "1")
01277                 )
01278         ;
01279         //TODO: we only test constructor here, check other things...
01280 
01281         delete fileLog;
01282 
01283         // Remove file from disk
01284         EXPECT_TRUE(boost::filesystem::remove(boost::filesystem::path(infoFileName)));
01285         EXPECT_TRUE(boost::filesystem::remove(boost::filesystem::path(warningFileName)));
01286 }
01287 
01288 
01289 //---------------------------
01290 // Main
01291 //---------------------------
01292 int main(int argc, char **argv)
01293 {
01294         dataPath = "";
01295         for(int i=1; i < argc; i++)
01296         {
01297                 if (strcmp(argv[i], "--path") == 0 && i+1 < argc)
01298                         dataPath = argv[i+1];
01299         }
01300 
01301         if(dataPath == "")
01302         {
01303                 cerr << "Missing the flag --path ./path/to/examples/data\n Please give the path to the test data folder which should be included with the source code. The folder is named 'examples/data'." << endl;
01304                 return -1;
01305         }
01306 
01307         // Load point cloud for all test
01308         ref2D =  DP::load(dataPath + "2D_oneBox.csv");
01309         data2D = DP::load(dataPath + "2D_twoBoxes.csv");
01310         ref3D =  DP::load(dataPath + "car_cloud400.csv");
01311         data3D = DP::load(dataPath + "car_cloud401.csv");
01312 
01313         // Result of data express in ref (from visual inspection)
01314         validT2d = PM::TransformationParameters(3,3);
01315         validT2d <<  0.987498,  0.157629, 0.0859918,
01316                                 -0.157629,  0.987498,  0.203247,
01317                                                 0,         0,         1;
01318 
01319         validT3d = PM::TransformationParameters(4,4);
01320         validT3d <<   0.982304,   0.166685,  -0.0854066,  0.0446816,
01321                                  -0.150189,   0.973488,   0.172524,   0.191998,
01322                                   0.111899,  -0.156644,   0.981296,  -0.0356313,
01323                       0,          0,          0,          1;
01324 
01325         testing::GTEST_FLAG(print_time) = true;
01326         testing::InitGoogleTest(&argc, argv);
01327         return RUN_ALL_TESTS();
01328 }
01329 
01330 
01331 


upstream_src
Author(s):
autogenerated on Wed Sep 24 2014 10:42:00