test_point_cloud_random_sampler_with_normal.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020, the mcl_3dl authors
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <gtest/gtest.h>
31 
32 #include <algorithm>
33 #include <vector>
34 
35 #include <pcl/point_types.h>
36 
38 #include <mcl_3dl/point_types.h>
39 
40 namespace mcl_3dl
41 {
42 namespace test
43 {
44 std::vector<State6DOF> buildPoseCovarianceMatrix(const double yaw,
45  const double front_std_dev,
46  const double side_std_dev)
47 {
48  Eigen::Matrix2d vt;
49  vt(0, 0) = std::cos(yaw);
50  vt(0, 1) = -std::sin(yaw);
51  vt(1, 0) = std::sin(yaw);
52  vt(1, 1) = std::cos(yaw);
53  Eigen::Matrix2d m;
54  m(0, 0) = std::pow(front_std_dev, 2);
55  m(0, 1) = 0;
56  m(1, 0) = 0;
57  m(1, 1) = std::pow(side_std_dev, 2);
58  const Eigen::Matrix2d xv_cov = vt.transpose() * m * vt;
59 
60  std::vector<State6DOF> result(6);
61  for (auto& state : result)
62  {
63  for (size_t i = 0; i < 6; ++i)
64  {
65  state[i] = 0.0;
66  }
67  }
68  result[0][0] = xv_cov(0, 0);
69  result[1][0] = xv_cov(1, 0);
70  result[0][1] = xv_cov(0, 1);
71  result[1][1] = xv_cov(1, 1);
72  return result;
73 }
74 
75 void buildWall(pcl::PointCloud<PointXYZIL>::Ptr result_points, double rotation_angle, int wall_length)
76 {
77  pcl::PointCloud<PointXYZIL> points;
78  for (int ny = 0; ny < wall_length; ++ny)
79  {
80  for (int nz = 0; nz < wall_length; ++nz)
81  {
82  PointXYZIL point;
83  point.x = 20.0;
84  point.y = (ny - wall_length / 2) * 0.05;
85  point.z = (nz - wall_length / 2) * 0.05;
86  point.label = 0;
87  point.intensity = 3000;
88  points.push_back(point);
89  }
90  }
91  const State6DOF s(mcl_3dl::Vec3(0, 0, 0), mcl_3dl::Quat(mcl_3dl::Vec3(0, 0, 1), rotation_angle));
92  s.transform(points);
93  result_points->insert(result_points->end(), points.begin(), points.end());
94 }
95 
97 {
98  pcl::PointCloud<PointXYZIL>::Ptr pc(new pcl::PointCloud<PointXYZIL>());
99  int wall_length = 20;
100  // Wall at right angles to the first principal component of particles
101  buildWall(pc, 0, wall_length);
102  // Wall parallel to the first principal component of particles
103  buildWall(pc, M_PI / 2, wall_length);
104 
105  const double robot_yaw = M_PI / 6;
106  const State6DOF mean(mcl_3dl::Vec3(3.5, -5.0, 0), mcl_3dl::Quat(mcl_3dl::Vec3(0, 0, 1), robot_yaw));
107  const std::vector<State6DOF> cov_matrix = buildPoseCovarianceMatrix(robot_yaw, 1.0, 0.2);
108 
109  // Fix random seeds to avoid flaky results
110  const std::vector<unsigned int> seeds =
111  {
112  12345,
113  23456,
114  34567,
115  45678,
116  56789,
117  };
118 
119  struct ParameterSet
120  {
121  double perform_weighting_ratio;
122  double max_weight_ratio;
123  double max_weight;
124  double expected_ratio_min;
125  double expected_ratio_max;
126  };
127  const std::vector<ParameterSet> parameters =
128  {
129  // Weights of points in the wall at right angles: 10, weights of points in the parallel wall: 1
130  {2.0, 4.0, 10.0, 0.85, 1.0}, // NOLINT(whitespace/braces)
131  // Weights of points in the wall at right angles: 1, weights of points in the parallel wall: 1
132  {6.0, 7.0, 10.0, 0.4, 0.6}, // NOLINT(whitespace/braces)
133  // Weights of points in the wall at right angles: 3, weights of points in the parallel wall: 1
134  {2.0, 8.0, 5.0, 0.65, 0.85}, // NOLINT(whitespace/braces)
135  };
136 
137  for (const unsigned int seed : seeds)
138  {
140  sampler.setParticleStatistics(mean, cov_matrix);
141  const int sample_num = 100;
142  for (const ParameterSet& parameter : parameters)
143  {
144  sampler.setParameters(parameter.perform_weighting_ratio, parameter.max_weight_ratio, parameter.max_weight, 0.4);
145  const pcl::PointCloud<PointXYZIL>::Ptr extracted_cloud = sampler.sample(pc, sample_num);
146  EXPECT_EQ(sample_num, static_cast<int>(extracted_cloud->size()));
147  // count[0] : numbers of points chosen from the wall at right angles
148  // count[1] : numbers of points chosen from the parallel wall
149  std::vector<int> counts(2, 0);
150  for (const auto& extracted_point : *extracted_cloud)
151  {
152  const auto pred = [&extracted_point](const PointXYZIL& p) { // NOLINT(whitespace/braces)
153  return (p.x == extracted_point.x) && (p.y == extracted_point.y) && (p.z == extracted_point.z);
154  };
155  const size_t index = std::find_if(pc->begin(), pc->end(), pred) - pc->begin();
156  ++counts[index / std::pow(wall_length, 2)];
157  }
158  const double ratio = static_cast<double>(counts[0]) / (counts[0] + counts[1]);
159  EXPECT_GE(ratio, parameter.expected_ratio_min) << "Failed at seed #" << seed;
160  EXPECT_LE(ratio, parameter.expected_ratio_max) << "Failed at seed #" << seed;
161  }
162  }
163 
165  sampler.setParticleStatistics(mean, cov_matrix);
166  pcl::PointCloud<PointXYZIL>::Ptr invalid_cloud(new pcl::PointCloud<PointXYZIL>());
167  // Empty cloud
168  EXPECT_EQ(0u, sampler.sample(invalid_cloud, 100)->size());
169  // Point cloud size is smaller than requested sample number
170  invalid_cloud->push_back(PointXYZIL());
171  EXPECT_EQ(1u, sampler.sample(invalid_cloud, 100)->size());
172 }
173 } // namespace test
174 } // namespace mcl_3dl
175 
176 int main(int argc, char** argv)
177 {
178  testing::InitGoogleTest(&argc, argv);
179 
180  return RUN_ALL_TESTS();
181 }
void buildWall(pcl::PointCloud< PointXYZIL >::Ptr result_points, double rotation_angle, int wall_length)
void transform(pcl::PointCloud< PointType > &pc) const
Definition: state_6dof.h:188
void setParameters(const double perform_weighting_ratio, const double max_weight_ratio, const double max_weight, const double normal_search_range)
XmlRpcServer s
int main(int argc, char **argv)
TEST(PointCloudSamplerWithNormal, Sampling)
void setParticleStatistics(const State6DOF &mean, const std::vector< State6DOF > &covariances)
std::vector< State6DOF > buildPoseCovarianceMatrix(const double yaw, const double front_std_dev, const double side_std_dev)
pcl::PointCloud< POINT_TYPE >::Ptr sample(const typename pcl::PointCloud< POINT_TYPE >::ConstPtr &pc, const size_t num) const final


mcl_3dl
Author(s): Atsushi Watanabe
autogenerated on Wed May 12 2021 02:16:29