00001
00063 #include <gtest/gtest.h>
00064 #include <cob_3d_mapping_common/polygon.h>
00065 #include <cob_3d_mapping_common/ros_msg_conversions.h>
00066 #include <pcl/common/eigen.h>
00067
00068
00069 struct PolygonData
00070 {
00071 PolygonData(unsigned int id,
00072 std::vector<float> color,
00073 Eigen::Vector3f normal,
00074 Eigen::Vector3f x_axis,
00075 Eigen::Vector3f origin,
00076 std::vector<std::vector<Eigen::Vector2f> > contours,
00077 std::vector<bool> holes)
00078 {
00079 id_ = id;
00080 color_ = color;
00081 normal_ = normal.normalized();
00082 origin_ = origin;
00083 d_ = origin_.dot(normal_);
00084 if (d_ > 0) {
00085 normal_ = -normal_;
00086 d_ = -d_;
00087 }
00088 contours_2d_ = contours;
00089 holes_ = holes;
00090 Eigen::Affine3f t;
00091 pcl::getTransformationFromTwoUnitVectorsAndOrigin(normal_.cross(x_axis), normal_, origin_, t);
00092 pose_ = t.inverse();
00093 for(unsigned int i = 0; i < contours_2d_.size(); i++)
00094 {
00095 std::vector<Eigen::Vector3f> c_3d;
00096 for(unsigned int j = 0; j < contours_2d_[i].size(); j++)
00097 {
00098 Eigen::Vector3f p_3d = pose_ * Eigen::Vector3f(contours_2d_[i][j](0), contours_2d_[i][j](1), 0);
00099 c_3d.push_back(p_3d);
00100 }
00101 contours_3d_.push_back(c_3d);
00102 }
00103 }
00104
00105 unsigned int id_;
00106 std::vector<float> color_;
00107 Eigen::Vector3f normal_;
00108 double d_;
00109 Eigen::Vector3f origin_;
00110 std::vector<std::vector<Eigen::Vector2f> > contours_2d_;
00111 std::vector<std::vector<Eigen::Vector3f> > contours_3d_;
00112 std::vector<bool> holes_;
00113 Eigen::Affine3f pose_;
00114 std::vector<unsigned int> merge_candidates_;
00115 };
00116
00117 class PolygonTest : public ::testing::Test
00118 {
00119 protected:
00120 virtual void
00121 SetUp ()
00122 {
00123
00124 std::vector<std::vector<Eigen::Vector2f> > contours;
00125 Eigen::Vector2f p1(0,0), p2(0,1), p3(1,1), p4(1,0);
00126 std::vector<Eigen::Vector2f> c;
00127 c.push_back(p1);
00128 c.push_back(p2);
00129 c.push_back(p3);
00130 c.push_back(p4);
00131 contours.push_back(c);
00132 std::vector<bool> holes;
00133 holes.push_back(false);
00134 PolygonData* pd1 = new PolygonData(0, std::vector<float>(4,1), Eigen::Vector3f(0,0,-1), Eigen::Vector3f(1,0,0), Eigen::Vector3f(-1,-1,1), contours, holes);
00135 pd_.push_back(pd1);
00136
00137
00138 contours.clear();
00139 Eigen::Vector2f p5(0.5,0.5);
00140 c.push_back(p5);
00141 contours.push_back(c);
00142
00143
00144 Eigen::Vector3f normal(0,0.1,-1);
00145 normal.normalize();
00146 PolygonData* pd2 = new PolygonData(1, std::vector<float>(4,1), normal, Eigen::Vector3f(1,0,0), Eigen::Vector3f(-0.5,-1,1), contours, holes);
00147 pd_.push_back(pd2);
00148
00149
00150 Eigen::Vector2f p6(0.8, 0.8), p7(0.8, 0.6), p8(0.6, 0.8);
00151 std::vector<Eigen::Vector2f> c_hole;
00152 c_hole.push_back(p6);
00153 c_hole.push_back(p7);
00154 c_hole.push_back(p8);
00155 contours.push_back(c_hole);
00156 holes.push_back(true);
00157 PolygonData* pd3 = new PolygonData(2, std::vector<float>(4,1), normal, Eigen::Vector3f(1,0,0), Eigen::Vector3f(-0.5,-1,1), contours, holes);
00158 pd_.push_back(pd3);
00159
00160 pd_[0]->merge_candidates_.push_back(0);
00161 pd_[0]->merge_candidates_.push_back(1);
00162 pd_[0]->merge_candidates_.push_back(2);
00163 pd_[1]->merge_candidates_.push_back(0);
00164 pd_[1]->merge_candidates_.push_back(1);
00165 pd_[1]->merge_candidates_.push_back(2);
00166 pd_[2]->merge_candidates_.push_back(0);
00167 pd_[2]->merge_candidates_.push_back(1);
00168 pd_[2]->merge_candidates_.push_back(2);
00169 }
00170
00171 std::vector<PolygonData*> pd_;
00172
00173 };
00174
00175 TEST_F(PolygonTest, creationWorks)
00176 {
00177 for(unsigned int i = 0; i < pd_.size(); i++)
00178 {
00179 cob_3d_mapping::Polygon p(pd_[i]->id_, pd_[i]->normal_, pd_[i]->origin_, pd_[i]->contours_3d_, pd_[i]->holes_, pd_[i]->color_);
00180 EXPECT_NEAR(pd_[i]->normal_.dot(p.normal_), 1.0, 0.001);
00181 EXPECT_NEAR(pd_[i]->d_, p.d_, 0.001);
00182 EXPECT_NEAR((p.pose_.rotation() * Eigen::Vector3f(0,0,1)).dot(pd_[i]->normal_), 1.0, 0.001);
00183 EXPECT_NEAR((p.pose_.translation() - pd_[i]->origin_).norm(), 0, 0.001);
00184 std::vector<std::vector<Eigen::Vector3f> > c_3d = p.getContours3D();
00185
00186 for(unsigned int j = 0; j < c_3d.size(); j++)
00187 {
00188 for(unsigned int k = 0; k < c_3d[j].size(); k++)
00189 {
00190 EXPECT_NEAR((pd_[i]->contours_3d_[j][k] - c_3d[j][k]).norm(), 0, 0.001);
00191
00192
00193 }
00194 }
00195 }
00196 }
00197
00198 TEST_F(PolygonTest, mergeUnion)
00199 {
00200 cob_3d_mapping::Polygon::Ptr p0(new cob_3d_mapping::Polygon(pd_[0]->id_, pd_[0]->normal_, pd_[0]->origin_, pd_[0]->contours_3d_, pd_[0]->holes_, pd_[0]->color_));
00201 std::vector<cob_3d_mapping::Polygon::Ptr> p_vec;
00202 cob_3d_mapping::Polygon::Ptr p1(new cob_3d_mapping::Polygon(pd_[1]->id_, pd_[1]->normal_, pd_[1]->origin_, pd_[1]->contours_3d_, pd_[1]->holes_, pd_[1]->color_));
00203 p_vec.push_back(p1);
00204
00205 p0->merge(p_vec);
00206 EXPECT_EQ(p0->merged_, 2);
00207 EXPECT_NEAR(p0->normal_.dot((0.5 * (pd_[0]->normal_ + pd_[1]->normal_)).normalized()), 1, 0.001);
00208
00209
00210
00211
00212
00213
00214
00215 }
00216
00217 TEST_F(PolygonTest, mergingWorks)
00218 {
00219 std::vector<cob_3d_mapping::Polygon::Ptr> p_vec;
00220 for(unsigned int i = 0; i < pd_.size(); i++)
00221 {
00222 cob_3d_mapping::Polygon::Ptr p(new cob_3d_mapping::Polygon(pd_[i]->id_, pd_[i]->normal_, pd_[i]->origin_, pd_[i]->contours_3d_, pd_[i]->holes_, pd_[i]->color_));
00223 p_vec.push_back(p);
00224 }
00225
00226
00227 std::vector<int> intersections;
00228 p_vec[0]->getMergeCandidates(p_vec, intersections);
00229
00230 EXPECT_EQ(intersections.size(), pd_[0]->merge_candidates_.size());
00231 std::vector<cob_3d_mapping::Polygon::Ptr> merge_candidates;
00232 double sum_area = 0;
00233 for(unsigned int i = 0; i < intersections.size(); i++)
00234 {
00235 merge_candidates.push_back(p_vec[i]);
00236 sum_area += p_vec[i]->computeArea3d();
00237 }
00238 p_vec[0]->merge(merge_candidates);
00239 EXPECT_EQ(p_vec[0]->merged_, pd_[0]->merge_candidates_.size()+1);
00240 EXPECT_LE(p_vec[0]->computeArea3d(), sum_area);
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 }
00259
00260 TEST_F(PolygonTest, transformWorks)
00261 {
00262 Eigen::Affine3f t(Eigen::Affine3f::Identity());
00263 t.translate(Eigen::Vector3f(-1,1,2));
00264 t.rotate(Eigen::AngleAxisf(0.5, Eigen::Vector3f(1,1,1)));
00265 for(unsigned int i = 0; i < pd_.size(); i++)
00266 {
00267 cob_3d_mapping::Polygon::Ptr p(new cob_3d_mapping::Polygon(pd_[i]->id_, pd_[i]->normal_, pd_[i]->origin_, pd_[i]->contours_3d_, pd_[i]->holes_, pd_[i]->color_));
00268 Eigen::Affine3f p0 = p->pose_;
00269 p->transform(t);
00270 p->transform(t.inverse());
00271 EXPECT_NEAR(p->normal_.dot(pd_[i]->normal_), 1, 0.001);
00272 EXPECT_NEAR(p->d_, pd_[i]->d_, 0.001);
00273 Eigen::Affine3f dt = p->pose_*p0.inverse();
00274
00275
00276
00277 EXPECT_TRUE(p->pose_.isApprox(p0));
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 }
00291 }
00292
00293 TEST_F(PolygonTest, msgConversionWorks)
00294 {
00295 for(unsigned int i = 0; i < pd_.size(); i++)
00296 {
00297 cob_3d_mapping::Polygon::Ptr p(new cob_3d_mapping::Polygon(pd_[i]->id_, pd_[i]->normal_, pd_[i]->origin_, pd_[i]->contours_3d_, pd_[i]->holes_, pd_[i]->color_));
00298 cob_3d_mapping_msgs::Shape s;
00299 cob_3d_mapping::toROSMsg(*p, s);
00300 cob_3d_mapping::Polygon p1;
00301 cob_3d_mapping::fromROSMsg(s, p1);
00302
00303 EXPECT_EQ(p->id_, p1.id_);
00304 EXPECT_EQ(p->contours_.size(), p1.contours_.size());
00305 EXPECT_EQ(p->holes_.size(), p1.holes_.size());
00306 EXPECT_NEAR(p->d_, p1.d_, 0.00001);
00307 EXPECT_NEAR((p->normal_ - p1.normal_).norm(), 0, 0.001);
00308 EXPECT_TRUE(p->pose_.isApprox(p1.pose_));
00309 EXPECT_NEAR(p->merge_weight_, p1.merge_weight_, 0.00001);
00310 EXPECT_NEAR((p->color_[0] - p1.color_[0]), 0, 0.001);
00311 EXPECT_NEAR((p->color_[1] - p1.color_[1]), 0, 0.001);
00312 EXPECT_NEAR((p->color_[2] - p1.color_[2]), 0, 0.001);
00313 EXPECT_NEAR((p->color_[3] - p1.color_[3]), 0, 0.001);
00314 for(unsigned int j = 0; j < p->contours_.size(); j++)
00315 {
00316 for(unsigned int k = 0; k < p->contours_[j].size(); k++)
00317 {
00318 EXPECT_NEAR((p->contours_[j][k] - p1.contours_[j][k]).norm(), 0, 0.001);
00319 }
00320 EXPECT_EQ(p->holes_[j], p1.holes_[j]);
00321 }
00322 }
00323 }
00324
00325
00326
00327
00328 int main(int argc, char **argv)
00329 {
00330 testing::InitGoogleTest(&argc, argv);
00331 return RUN_ALL_TESTS();
00332 }