Go to the documentation of this file.00001
00064
00065 #include <ros/ros.h>
00066 #include <pcl/point_types.h>
00067 #define PCL_MINOR (PCL_VERSION[2] - '0')
00068
00069 #include <pcl_ros/transforms.h>
00070 #include <pcl_ros/point_cloud.h>
00071 #include <pcl/io/pcd_io.h>
00072 #include <pcl/kdtree/kdtree.h>
00073 #include <pcl/kdtree/kdtree_flann.h>
00074 #include <pcl/registration/transformation_estimation_svd.h>
00075
00076 #include <boost/random.hpp>
00077 #include <boost/random/normal_distribution.hpp>
00078
00079 #define ADD_NOISE() \
00080 p.x+=var_nor();\
00081 p.y+=var_nor();\
00082 p.z+=var_nor();
00083
00084 pcl::PointCloud<pcl::PointXYZ> generateData(int data) {
00085
00086 boost::mt19937 rng;
00087 rng.seed(clock());
00088
00089 boost::normal_distribution<> nd(0, 0.1*data);
00090
00091 boost::variate_generator<boost::mt19937&,
00092 boost::normal_distribution<> > var_nor(rng, nd);
00093
00094 pcl::PointCloud<pcl::PointXYZ> pc;
00095 for(int i=0; i<100; i++) {
00096 pcl::PointXYZ p;
00097
00098 p.x=(i-50)/50.;
00099 p.y=0;
00100 p.z=1;
00101 ADD_NOISE();
00102 pc.push_back(p);
00103
00104 p.y=1;
00105 ADD_NOISE();
00106 pc.push_back(p);
00107
00108 p.z=2;
00109 ADD_NOISE();
00110 pc.push_back(p);
00111
00112 p.y=0;
00113 ADD_NOISE();
00114 pc.push_back(p);
00115 }
00116 for(int i=1; i<99; i++) {
00117 pcl::PointXYZ p;
00118
00119 p.x=-1;
00120 p.y=0;
00121 p.z=1+i/100.;
00122 ADD_NOISE();
00123 pc.push_back(p);
00124
00125 p.x=1;
00126 ADD_NOISE();
00127 pc.push_back(p);
00128
00129 p.y=1;
00130 ADD_NOISE();
00131 pc.push_back(p);
00132
00133 p.x=-1;
00134 ADD_NOISE();
00135 pc.push_back(p);
00136 }
00137
00138 return pc;
00139 }
00140
00141 void generateTF(int trans, Eigen::Quaternionf &R, Eigen::Vector3f &t, Eigen::Matrix3f &mR)
00142 {
00143 float strengthR=(trans%3)*0.05;
00144 trans/=3;
00145 float strengthT=(trans%3)*0.05;
00146 trans/=3;
00147
00148 int temp=trans%8;
00149 Eigen::Vector3f axis;
00150 axis(0) = temp&1?1:0;
00151 axis(1) = temp&2?1:0;
00152 axis(2) = temp&4?1:0;
00153 trans/=8;
00154
00155 Eigen::AngleAxisf aa(strengthR,axis);
00156 R = aa.toRotationMatrix();
00157 mR= R.toRotationMatrix();
00158 R = mR;
00159
00160 t(0) = temp&1?1:0;
00161 if(temp&2) t(0)=-t(0);
00162 t(1) = temp&4?1:0;
00163 if(temp&8) t(1)=-t(1);
00164 t(2) = temp&16?1:0;
00165 if(temp&32) t(2)=-t(2);
00166 trans/=64;
00167
00168 t*=strengthT;
00169 }
00170
00171 void transform(pcl::PointCloud<pcl::PointXYZ> &pc, Eigen::Quaternionf &R, Eigen::Vector3f &t)
00172 {
00173 Eigen::Matrix4f m = Eigen::Matrix4f::Identity();
00174 for(int i=0; i<3; i++)
00175 for(int j=0; j<3; j++)
00176 m(i,j) = R.toRotationMatrix()(i,j);
00177 m.col(3).head<3>() = t;
00178
00179 pcl::transformPointCloud(pc,pc,m);
00180 }
00181
00182 void addNoise(pcl::PointCloud<pcl::PointXYZ> &pc, int noise)
00183 {
00184
00185 boost::mt19937 rng;
00186 rng.seed(clock());
00187
00188 boost::normal_distribution<> nd(0, 0.02*noise);
00189
00190 boost::variate_generator<boost::mt19937&,
00191 boost::normal_distribution<> > var_nor(rng, nd);
00192
00193 for(int i=0; i<pc.size(); i++) {
00194 pcl::PointXYZ &p = pc[i];
00195 ADD_NOISE();
00196 }
00197
00198 }
00199
00200 FILE *fp = NULL;
00201 void write(const char *str)
00202 {
00203 ROS_ASSERT(fp);
00204 fputs(str,fp);
00205 }
00206 void write(const int n)
00207 {
00208 char str[128];
00209 sprintf(str,"%d",n);
00210 write(str);
00211 }
00212 void write(const float n)
00213 {
00214 char str[128];
00215 sprintf(str,"%f",n);
00216 write(str);
00217 }
00218
00219 int main(int argc, char **argv) {
00220 if(argc<2) {
00221 printf("specify output path");
00222 return 1;
00223 }
00224
00225 fp = fopen(argv[1],"w");
00226
00227 write("<svd>");
00228
00229 pcl::PointCloud<pcl::PointXYZ> pc1, pc2;
00230
00231 std::cout<<"\n";
00232 for(int trans=0; trans<3*3*8*64; trans++) {
00233 if( !(trans/(3*3*8))&1 && (trans/(3*3*8))&2 )
00234 continue;
00235 if( !(trans/(3*3*8))&4 && (trans/(3*3*8))&8 )
00236 continue;
00237 if( !(trans/(3*3*8))&16 && (trans/(3*3*8))&32 )
00238 continue;
00239 std::cout<<(trans*100/(10*10*8*64))<<"%\r";
00240 Eigen::Quaternionf R;
00241 Eigen::Vector3f t;
00242
00243 Eigen::Matrix3f mR_cmp;
00244 generateTF(trans, R,t,mR_cmp);
00245
00246 for(int data=0; data<10; data++) {
00247 pc1=generateData(data);
00248
00249 pc2=pc1;
00250 transform(pc2,R,t);
00251
00252 for(int noise=0; noise<=10; noise++)
00253 {
00254 addNoise(pc2, noise);
00255
00256
00257 pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> trans_est;
00258 Eigen::Matrix4f m=Eigen::Matrix4f::Identity();
00259 trans_est.estimateRigidTransformation (pc1, pc2, m);
00260
00261 Eigen::Matrix3f m2;
00262 for(int i=0; i<3; i++)
00263 for(int j=0; j<3; j++)
00264 m2(i,j)=m(i,j);
00265
00266
00267 Eigen::Quaternionf Rn(m2);
00268 Eigen::Vector3f tn = m.col(3).head<3>();
00269
00270 float error_r = Rn.angularDistance(R);
00271 float error_d = (tn-t).norm();
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 write("<set>");
00284
00285 write("<trans>");
00286 write((trans));
00287 write("</trans>");
00288
00289 write("<data>");
00290 write((data));
00291 write("</data>");
00292
00293 write("<noise>");
00294 write((noise));
00295 write("</noise>");
00296
00297 write("<error_r>");
00298 write((error_r));
00299 write("</error_r>");
00300
00301 write("<error_d>");
00302 write((error_d));
00303 write("</error_d>");
00304
00305 write("</set>");
00306 }
00307 }
00308 }
00309
00310 write("</svd>");
00311
00312 fclose(fp);
00313 return 0;
00314 }