00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <industrial_extrinsic_cal/ceres_costs_utils.hpp>
00021
00022 #include <gtest/gtest.h>
00023 #include <yaml-cpp/yaml.h>
00024 #include <fstream>
00025 #include <iostream>
00026
00027 #include <Eigen/Geometry>
00028 #include <Eigen/Core>
00029
00030 using namespace industrial_extrinsic_cal;
00031
00032 Point3d transformPoint(Point3d &original_point, double &ax, double &ay, double &az, double &x, double&y, double &z);
00033
00034 std::vector<Point3d> created_points;
00035 double aa[3];
00036 double p[3];
00037 std::vector<Point3d> transformed_points;
00038
00039 struct PointReprjErrorNoDistortion
00040 {
00041 PointReprjErrorNoDistortion(double ob_x, double ob_y, double fx) :
00042 px_(ob_x), py_(ob_y), pz_(fx)
00043 {
00044 }
00045
00046 template<typename T>
00047 bool operator()(const T* const c_p1,
00048
00049 const T* point,
00050 T* resid) const
00051 {
00053 int q = 0;
00054 const T& x = c_p1[0];
00055 const T& y = c_p1[1];
00056 const T& z = c_p1[2];
00057 const T& tx = c_p1[3];
00058 const T& ty = c_p1[4];
00059 const T& tz = c_p1[5];
00061
00062
00063
00064
00065
00066
00067
00068
00070 T aa[3];
00071 T p[3];
00072 aa[0] = x;
00073 aa[1] = y;
00074 aa[2] = z;
00075 ceres::AngleAxisRotatePoint(aa, point, p);
00076
00078 T xp1 = p[0] + tx;
00079 T yp1 = p[1] + ty;
00080 T zp1 = p[2] + tz;
00081
00085 T xp=xp1;
00086 T yp=yp1;
00087 T zp=zp1;
00088
00092 resid[0] = T(xp)-T(px_);
00093 resid[1] = T(yp)-T(py_);
00094 resid[2] = T(zp)-T(pz_);
00095
00096 return true;
00097 }
00101 static ceres::CostFunction* Create(const double p_x, const double p_y, const double p_z)
00102 {
00103 return (new ceres::AutoDiffCostFunction<PointReprjErrorNoDistortion, 3, 6, 3>(new PointReprjErrorNoDistortion(p_x, p_y, p_z)));
00104 }
00105 double px_;
00106 double py_;
00107 double pz_;
00108 };
00109
00110 TEST(IndustrialExtrinsicCalCeresSuite, create_points)
00111 {
00112 Point3d x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20;
00113 x1.pb[0]=1.0;x1.pb[1]=1.0;x1.pb[2]=1;
00114 created_points.push_back(x1);
00115 x2.pb[0]=0;x2.pb[1]=0;x2.pb[2]=0.01;
00116 created_points.push_back(x2);
00117 x3.pb[0]=0.65;x3.pb[1]=0.94;x3.pb[2]=0.01;
00118 created_points.push_back(x3);
00119 x4.pb[0]=0.2;x4.pb[1]=0.3;x4.pb[2]=0.01;
00120 created_points.push_back(x4);
00121 x5.pb[0]=0.372;x5.pb[1]=0.4;x5.pb[2]=0.4;
00122 created_points.push_back(x5);
00123 x6.pb[0]=0.3762;x6.pb[1]=0.8;x6.pb[2]=0.3;
00124 created_points.push_back(x6);
00125 x7.pb[0]=0.4;x7.pb[1]=0.389;x7.pb[2]=0.4;
00126 created_points.push_back(x7);
00127 x8.pb[0]=0.431;x8.pb[1]=0.7;x8.pb[2]=0.7;
00128 created_points.push_back(x8);
00129 x9.pb[0]=0.535;x9.pb[1]=0.9;x9.pb[2]=0.01;
00130 created_points.push_back(x9);
00131 x10.pb[0]=0.596;x10.pb[1]=1;x10.pb[2]=1.0;
00132 created_points.push_back(x10);
00133 x11.pb[0]=0.24;x11.pb[1]=1.0;x11.pb[2]=0.01;
00134 created_points.push_back(x11);
00135 x12.pb[0]=0.673;x12.pb[1]=1.7;x12.pb[2]=0.8;
00136 created_points.push_back(x12);
00137 x13.pb[0]=0.552;x13.pb[1]=1.15;x13.pb[2]=0.01;
00138 created_points.push_back(x13);
00139 x14.pb[0]=0.56;x14.pb[1]=0.81;x14.pb[2]=0.01;
00140 created_points.push_back(x14);
00141 x15.pb[0]=.70;x15.pb[1]=1.10;x15.pb[2]=0.01;
00142 created_points.push_back(x15);
00143 x16.pb[0]=0.3762;x16.pb[1]=0.02435;x16.pb[2]=0.3;
00144 created_points.push_back(x16);
00145 x17.pb[0]=0.0234;x17.pb[1]=0.389;x17.pb[2]=0.132;
00146 created_points.push_back(x17);
00147 x18.pb[0]=0.431;x18.pb[1]=0.245;x18.pb[2]=0.0235;
00148 created_points.push_back(x18);
00149 x19.pb[0]=0.535;x19.pb[1]=0.673;x19.pb[2]=0.01;
00150 created_points.push_back(x19);
00151 x20.pb[0]=0.76;x20.pb[1]=0.453;x20.pb[2]=1.0;
00152 created_points.push_back(x20);
00153 std::cout<<"Original Point 1: "<<x1.pb[0]<<" "<<x1.pb[1]<<" "<<x1.pb[2]<<std::endl;
00154
00155
00156 aa[0] = 2.7;
00157 aa[1] = 0.3;
00158 aa[2] = 0.1;
00159 p[0]=0.2;
00160 p[1]=0.4;
00161 p[2]=0.5;
00162 Point3d t_point;
00163 for (int i=0; i<created_points.size();i++)
00164 {
00165 t_point=transformPoint(created_points.at(i), aa[0], aa[1], aa[2], p[0], p[1], p[2]);
00166 transformed_points.push_back(t_point);
00167 }
00168
00169 }
00170
00171 TEST(IndustrialExtrinsicCalCeresSuite, points_costfunction)
00172 {
00173 double extrinsics[6];
00174 ceres::Problem problem;
00175 for (int j = 0; j < transformed_points.size(); ++j)
00176 {
00177 ceres::CostFunction* cost_function = PointReprjErrorNoDistortion::Create(transformed_points.at(j).pb[0], transformed_points.at(j).pb[1], transformed_points.at(j).pb[2]);
00178
00179 problem.AddResidualBlock(cost_function, NULL, extrinsics, created_points[j].pb);
00180
00181 problem.SetParameterBlockConstant(created_points[j].pb);
00182 }
00183 ceres::Solver::Options options;
00184 options.linear_solver_type = ceres::DENSE_SCHUR;
00185 options.minimizer_progress_to_stdout = false;
00186 options.max_num_iterations = 1000;
00187
00188 ceres::Solver::Summary summary;
00189 ceres::Solve(options, &problem, &summary);
00190
00191 std::cout << summary.BriefReport() << "\n";
00192
00193 EXPECT_FLOAT_EQ(-2.7,extrinsics[0]);
00194 EXPECT_FLOAT_EQ(-0.3,extrinsics[1]);
00195 EXPECT_FLOAT_EQ(-0.1,extrinsics[2]);
00196 EXPECT_FLOAT_EQ(0.2,extrinsics[3]);
00197 EXPECT_FLOAT_EQ(0.4,extrinsics[4]);
00198 EXPECT_FLOAT_EQ(0.5,extrinsics[5]);
00199 std::cout<<"Original aa rot and translation: "<<aa[0]<<" "<<aa[1]<<" "<<aa[2]
00200 <<" "<<p[0]<<" "<<p[1]<<" "<<p[2]<<std::endl;
00201
00202 std::cout<<"Optimized Extrinsics rot/transl: "<<extrinsics[0]<<" "<<extrinsics[1]<<" "<<extrinsics[2]<<" "
00203 <<extrinsics[3]<<" "<<extrinsics[4]<<" "<<extrinsics[5]<<std::endl;
00204 }
00205
00206 TEST(DISABLED_IndustrialExtrinsicCalCeresSuite, camera_costfunction)
00207
00208 {
00209 CameraParameters c_parameters;
00210 c_parameters.angle_axis[0]=0.0;
00211 c_parameters.angle_axis[1]=0.0;
00212 c_parameters.angle_axis[2]=0.0;
00213 c_parameters.position[0]=0.0;
00214 c_parameters.position[1]=0.0;
00215 c_parameters.position[2]=0.0;
00216 c_parameters.focal_length_x=525;
00217 c_parameters.focal_length_y=525;
00218 c_parameters.center_x=320;
00219 c_parameters.center_y=240;
00220 c_parameters.distortion_k1=0.01;
00221 c_parameters.distortion_k2=0.02;
00222 c_parameters.distortion_k3=0.03;
00223 c_parameters.distortion_p1=0.01;
00224 c_parameters.distortion_p2=0.01;
00225
00226 std::vector<Observation> projected_observations;
00227 Observation proj_point;
00228 for (int m=0; m<transformed_points.size(); m++)
00229 {
00230 proj_point=industrial_extrinsic_cal::projectPointWithDistortion(c_parameters, transformed_points.at(m));
00231 projected_observations.push_back(proj_point);
00232 }
00233
00234 double extrinsics[6];
00235 extrinsics[0]=c_parameters.pb_extrinsics[0];
00236 extrinsics[1]=c_parameters.pb_extrinsics[1];
00237 extrinsics[2]=c_parameters.pb_extrinsics[2];
00238 extrinsics[3]=c_parameters.pb_extrinsics[3];
00239 extrinsics[4]=c_parameters.pb_extrinsics[4];
00240 extrinsics[5]=c_parameters.pb_extrinsics[5];
00241 ceres::Problem problem;
00242 double original_points[3];
00243 for (int j = 0; j < projected_observations.size(); ++j)
00244 {
00245 ceres::CostFunction* cost_function = CameraReprjErrorWithDistortion::Create(projected_observations.at(j).image_loc_x,
00246 projected_observations.at(j).image_loc_y);
00247
00248
00249 problem.AddResidualBlock(cost_function, NULL, extrinsics, c_parameters.pb_intrinsics, created_points[j].pb);
00250 problem.SetParameterBlockConstant(c_parameters.pb_intrinsics);
00251 problem.SetParameterBlockConstant(created_points[j].pb);
00252 }
00253 ceres::Solver::Options options;
00254 options.linear_solver_type = ceres::DENSE_SCHUR;
00255 options.minimizer_progress_to_stdout = true;
00256 options.max_num_iterations = 1000;
00257
00258 ceres::Solver::Summary summary;
00259 ceres::Solve(options, &problem, &summary);
00260
00261 std::cout << summary.BriefReport() << "\n";
00262
00263 std::cout<<"Expected aa rot and translation: "<<aa[0]<<" "<<aa[1]<<" "<<aa[2]
00264 <<" "<<p[0]<<" "<<p[1]<<" "<<p[2]<<std::endl;
00265
00266 std::cout<<"Optimized Extrinsics rot/transl: "<<extrinsics[0]<<" "<<extrinsics[1]<<" "
00267 <<extrinsics[2]<<" "<<extrinsics[3]<<" "<<extrinsics[4]<<" "
00268 <<extrinsics[5]<<std::endl;
00269 }
00270
00271
00272 TEST(DISABLED_IndustrialExtrinsicCalCeresSuite, camera_no_dist_costfunction)
00273 {
00274 CameraParameters c_parameters;
00275 c_parameters.angle_axis[0]=0.0;
00276 c_parameters.angle_axis[1]=0.0;
00277 c_parameters.angle_axis[2]=0.0;
00278 c_parameters.position[0]=0.0;
00279 c_parameters.position[1]=0.0;
00280 c_parameters.position[2]=0.0;
00281 c_parameters.focal_length_x=525;
00282 c_parameters.focal_length_y=525;
00283 c_parameters.center_x=320;
00284 c_parameters.center_y=240;
00285 c_parameters.distortion_k1=0.01;
00286 c_parameters.distortion_k2=0.02;
00287 c_parameters.distortion_k3=0.03;
00288 c_parameters.distortion_p1=0.01;
00289 c_parameters.distortion_p2=0.01;
00290
00291 std::vector<Observation> projected_observations;
00292 Observation proj_point;
00293 for (int m=0; m<transformed_points.size(); m++)
00294 {
00295
00296 proj_point=industrial_extrinsic_cal::projectPointNoDistortion(c_parameters, transformed_points.at(m));
00297 projected_observations.push_back(proj_point);
00298 }
00299
00300 double extrinsics[6];
00301 extrinsics[0]=c_parameters.pb_extrinsics[0];
00302 extrinsics[1]=c_parameters.pb_extrinsics[1];
00303 extrinsics[2]=c_parameters.pb_extrinsics[2];
00304 extrinsics[3]=c_parameters.pb_extrinsics[3];
00305 extrinsics[4]=c_parameters.pb_extrinsics[4];
00306 extrinsics[5]=c_parameters.pb_extrinsics[5];
00307 ceres::Problem problem;
00308 for (int j = 0; j < projected_observations.size(); ++j)
00309 {
00310 ceres::CostFunction* cost_function = CameraReprjErrorNoDistortion::Create(projected_observations.at(j).image_loc_x,
00311 projected_observations.at(j).image_loc_y, c_parameters.focal_length_x, c_parameters.focal_length_y,
00312 c_parameters.center_x, c_parameters.center_y);
00313
00314 problem.AddResidualBlock(cost_function, NULL, extrinsics, c_parameters.pb_intrinsics, created_points.at(j).pb);
00315 problem.SetParameterBlockConstant(c_parameters.pb_intrinsics);
00316 problem.SetParameterBlockConstant(created_points.at(j).pb);
00317 }
00318 ceres::Solver::Options options;
00319 options.linear_solver_type = ceres::DENSE_SCHUR;
00320 options.minimizer_progress_to_stdout = true;
00321 options.max_num_iterations = 1000;
00322
00323 ceres::Solver::Summary summary;
00324 ceres::Solve(options, &problem, &summary);
00325
00326 std::cout << summary.BriefReport() << "\n";
00327
00328 std::cout<<"Expected aa rot and translation: "<<aa[0]<<" "<<aa[1]<<" "<<aa[2]
00329 <<" "<<p[0]<<" "<<p[1]<<" "<<p[2]<<std::endl;
00330
00331 std::cout<<"Optimized Extrinsics rot/transl: "<<extrinsics[0]<<" "<<extrinsics[1]<<" "
00332 <<extrinsics[2]<<" "<<extrinsics[3]<<" "<<extrinsics[4]<<" "
00333 <<extrinsics[5]<<std::endl;
00334 }
00335
00336 Point3d transformPoint(Point3d &original_point, double &ax, double &ay, double &az, double &x, double&y, double &z)
00337 {
00338
00339 Eigen::Matrix3f m_ceres;
00340 Eigen::Matrix3f m_eigen;
00341 m_eigen = Eigen::AngleAxisf(ax, Eigen::Vector3f::UnitX())
00342 * Eigen::AngleAxisf(ay, Eigen::Vector3f::UnitY())
00343 * Eigen::AngleAxisf(az, Eigen::Vector3f::UnitZ());
00344
00345 double aa[3];
00346 double p[3];
00347 aa[0] = ax;
00348 aa[1] = ay;
00349 aa[2] = az;
00350 Eigen::Vector3f orig_point(original_point.pb[0], original_point.pb[1], original_point.pb[2]);
00351
00352
00353 double R[9];
00354 ceres::AngleAxisToRotationMatrix(aa, R);
00355 m_ceres << R[0], R[1],R[2],
00356 R[3], R[4], R[5],
00357 R[6], R[7], R[8];
00358
00359 Eigen::Vector3f rot_point=m_ceres*orig_point;
00360
00361 double xp1 = rot_point.x() + x;
00362 double yp1 = rot_point.y() + y;
00363 double zp1 = rot_point.z() + z;
00364
00365 Point3d t_point;
00366 t_point.pb[0]=xp1;t_point.pb[1]=yp1;t_point.pb[2]=zp1;
00367
00368 return t_point;
00369 }
00370
00371
00372 int main(int argc, char **argv)
00373 {
00374
00375 testing::InitGoogleTest(&argc, argv);
00376 return RUN_ALL_TESTS();
00377
00378 }