ceres_cost_utils_test.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Apache License)
00003  *
00004  * Copyright (c) 2013, Southwest Research Institute
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *   http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include <industrial_extrinsic_cal/basic_types.h>
00020 #include <industrial_extrinsic_cal/observation_scene.h>
00021 
00022 namespace industrial_extrinsic_cal
00023 {
00024 Observation projectPoint(CameraParameters C, Point3d P)
00025 {
00026   double p[3];
00027   double pt[3];
00028   pt[0] = P.x;
00029   pt[1] = P.y;
00030   pt[2] = P.z;
00031 
00032   /* transform point into camera frame */
00033   /* note, camera transform takes points from camera frame into world frame */
00034   double aa[3];
00035   aa[0]=C.pb_extrinsics[0];
00036   aa[0]=C.pb_extrinsics[1];
00037   aa[0]=C.pb_extrinsics[2];
00038   ceres::AngleAxisRotatePoint(aa, pt, p);
00039 
00040   p[0] +=C.pb_extrinsics[3];
00041   p[1] +=C.pb_extrinsics[4];
00042   p[2] +=C.pb_extrinsics[5];
00043 
00044   double xp = p[0] / p[2];
00045   double yp = p[1] / p[2];
00046 
00047   // calculate terms for polynomial distortion
00048   double r2 = xp * xp + yp * yp;
00049   double r4 = r2 * r2;
00050   double r6 = r2 * r4;
00051 
00052   double xp2 = xp * xp; /* temporary variables square of others */
00053   double yp2 = yp * yp;
00054 
00055   /* apply the distortion coefficients to refine pixel location */
00056   double xpp = xp + C.distortion_k1 * r2 * xp + C.distortion_k2 * r4 * xp +
00057       C.distortion_k3 * r6 * xp + C.distortion_p2 * (r2 + 2 * xp2) + 2 * C.distortion_p1 * xp * yp;
00058   double ypp = yp + C.distortion_k1 * r2 * yp + C.distortion_k2 * r4 * yp +
00059       C.distortion_k3 * r6 * yp + C.distortion_p1 * (r2 + 2 * yp2) + 2 * C.distortion_p2 * xp * yp;
00060 
00061   /* perform projection using focal length and camera center into image plane */
00062   Observation O;
00063   O.point_id = 0;
00064   O.image_loc_x = C.focal_length_x * xpp + C.center_x;
00065   O.image_loc_y = C.focal_length_y * ypp + C.center_y;
00066   return (O);
00067 }
00068 
00069 struct CameraReprjErrorWithDistortion
00070 {
00071   CameraReprjErrorWithDistortion(double ob_x, double ob_y) :
00072       ox_(ob_x), oy_(ob_y)
00073   {
00074   }
00075 
00076   template<typename T>
00077     bool operator()(const T* const c_p1, 
00078                     const T* c_p2, 
00079                     const T* point, 
00080                     T* resid) const
00081     {
00083       int q = 0; 
00084       const T& x = c_p1[q++]; 
00085       const T& y = c_p1[q++]; 
00086       const T& z = c_p1[q++]; 
00087       const T& tx = c_p1[q++]; 
00088       const T& ty = c_p1[q++]; 
00089       const T& tz = c_p1[q++]; 
00091       q = 0; 
00092       const T& fx = c_p2[q++]; 
00093       const T& fy = c_p2[q++]; 
00094       const T& cx = c_p2[q++]; 
00095       const T& cy = c_p2[q++]; 
00096       const T& k1 = c_p2[q++]; 
00097       const T& k2 = c_p2[q++]; 
00098       const T& k3 = c_p2[q++]; 
00099       const T& p1 = c_p2[q++]; 
00100       const T& p2 = c_p2[q++]; 
00103       T aa[3];
00104       T p[3]; 
00105       aa[0] = x;
00106       aa[1] = y;
00107       aa[2] = z;
00108       ceres::AngleAxisRotatePoint(aa, point, p);
00109 
00111       T xp1 = p[0] + tx; 
00112       T yp1 = p[1] + ty;
00113       T zp1 = p[2] + tz;
00114 
00116       T xp = xp1 / zp1;
00117       T yp = yp1 / zp1;
00118 
00120       T r2 = xp * xp + yp * yp;
00121       T r4 = r2 * r2;
00122       T r6 = r2 * r4;
00123 
00124       T xp2 = xp * xp; 
00125       T yp2 = yp * yp;
00126       /*apply the distortion coefficients to refine pixel location */
00127       T xpp = xp + k1 * r2 * xp + k2 * r4 * xp + k3 * r6 * xp + p2 * (r2 + T(2.0) * xp2) + T(2.0) * p1 * xp * yp;
00128       T ypp = yp + k1 * r2 * yp + k2 * r4 * yp + k3 * r6 * yp + p1 * (r2 + T(2.0) * yp2) + T(2.0) * p2 * xp * yp;
00130       resid[0] = fx * xpp + cx - T(ox_);
00131       resid[1] = fy * ypp + cy - T(oy_);
00132 
00133       return true;
00134     } 
00138   static ceres::CostFunction* Create(const double o_x, const double o_y)
00139   {
00140     return (new ceres::AutoDiffCostFunction<CameraReprjErrorWithDistortion, 2, 6, 9, 3>(new CameraReprjErrorWithDistortion(o_x, o_y)));
00141   }
00142   double ox_; 
00143   double oy_; 
00144 };
00145 
00146 struct CameraReprjErrorNoDistortion
00147 {
00148   CameraReprjErrorNoDistortion(double ob_x, double ob_y) :
00149       ox_(ob_x), oy_(ob_y)
00150   {
00151   }
00152 
00153   template<typename T>
00154     bool operator()(const T* const c_p1, 
00155                     const T* c_p2, 
00156                     const T* point, 
00157                     T* resid) const
00158     {
00160       int q = 0; 
00161       const T& x = c_p1[q++]; 
00162       const T& y = c_p1[q++]; 
00163       const T& z = c_p1[q++]; 
00164       const T& tx = c_p1[q++]; 
00165       const T& ty = c_p1[q++]; 
00166       const T& tz = c_p1[q++]; 
00168       q = 0; 
00169       const T& fx = c_p2[q++]; 
00170       const T& fy = c_p2[q++]; 
00171       const T& cx = c_p2[q++]; 
00172       const T& cy = c_p2[q++]; 
00175       T aa[3];
00176       T p[3]; 
00177       aa[0] = x;
00178       aa[1] = y;
00179       aa[2] = z;
00180       ceres::AngleAxisRotatePoint(aa, point, p);
00181 
00183       T xp1 = p[0] + tx; 
00184       T yp1 = p[1] + ty;
00185       T zp1 = p[2] + tz;
00186 
00188       T xp = xp1 / zp1;
00189       T yp = yp1 / zp1;
00190 
00192       resid[0] = T(fx_) * xp + T(cx_) - T(ox_);
00193       resid[1] = T(fy_) * yp + T(cy_) - T(oy_);
00194 
00195       return true;
00196     } 
00200   static ceres::CostFunction* Create(const double o_x, const double o_y)
00201   {
00202     return (new ceres::AutoDiffCostFunction<CameraReprjErrorNoDistortion, 2, 6, 4, 3>(new CameraReprjErrorNoDistortion(o_x, o_y)));
00203   }
00204   double ox_; 
00205   double oy_; 
00206   double fx_; 
00207   double fy_; 
00208   double cx_; 
00209   double cy_; 
00210 };
00211 
00212 struct TargetCameraReprjErrorNoDistortion
00213 {
00214   TargetCameraReprjErrorNoDistortion(double ob_x, double ob_y) :
00215       ox_(ob_x), oy_(ob_y)
00216   {
00217   }
00218 
00219   template<typename T>
00220     bool operator()(const T* const c_p1, 
00221                     const T* const c_p2, 
00222                     const T* const c_p3, 
00223                     const T* const point, 
00224                     T* resid) const
00225     {
00226 
00228       int q = 0; 
00229       const T& ax = c_p1[q++]; 
00230       const T& ay = c_p1[q++]; 
00231       const T& az = c_p1[q++]; 
00232       const T& tx = c_p1[q++]; 
00233       const T& ty = c_p1[q++]; 
00234       const T& tz = c_p1[q++]; 
00236       q = 0; 
00237       const T& fx = c_p2[q++]; 
00238       const T& fy = c_p2[q++]; 
00239       const T& cx = c_p2[q++]; 
00240       const T& cy = c_p2[q++]; 
00242       q = 0; 
00243       const T& target_x = c_p3[q++]; 
00244       const T& target_y = c_p3[q++]; 
00245       const T& target_z = c_p3[q++]; 
00246       const T& target_ax = c_p3[q++]; 
00247       const T& target_ay = c_p3[q++]; 
00248       const T& target_az = c_p3[q++]; 
00251       T target_aa[3];
00252       T world_point_loc[3]; 
00253       target_aa[0] = target_ax;
00254       target_aa[1] = target_ay;
00255       target_aa[2] = target_az;
00256       ceres::AngleAxisRotatePoint(target_aa, point, world_point_loc);
00257 
00259       world_point_loc[0] = world_point_loc[0] + target_x;
00260       world_point_loc[1] = world_point_loc[1] + target_y;
00261       world_point_loc[2] = world_point_loc[2] + target_z;
00262 
00264       /*  Note that camera transform is from world into camera frame, not vise versa */
00265       T aa[3];
00266       T camera_point_loc[3]; 
00267       aa[0] = ax;
00268       aa[1] = ay;
00269       aa[2] = az;
00270       ceres::AngleAxisRotatePoint(aa, point, camera_point_loc);
00271 
00273       T xp1 = camera_point_loc[0] + tx; 
00274       T yp1 = camera_point_loc[1] + ty;
00275       T zp1 = camera_point_loc[2] + tz;
00276 
00278       T xp = xp1 / zp1;
00279       T yp = yp1 / zp1;
00280 
00282       resid[0] = fx * xp + cx - T(ox_);
00283       resid[1] = fy * yp + cy - T(oy_);
00284 
00285       return true;
00286     } 
00290   static ceres::CostFunction* Create(const double o_x, const double o_y)
00291   {
00292     return (new ceres::AutoDiffCostFunction<TargetCameraReprjErrorNoDistortion, 2, 6, 4, 6, 3>(
00293         new CameraReprjError(o_x, o_y)));
00294   }
00295   double ox_; 
00296   double oy_; 
00297 };
00298 
00299 struct TargetCameraReprjErrorProjModelAsClassVars
00300 {
00301   TargetCameraReprjErrorProjModelAsClassVars(double ob_x, double ob_y, double fx, double fy, double cx, double cy) :
00302       ox_(ob_x), oy_(ob_y), fx_(fx), fy_(fy), cx_(cx), cy_(cy)
00303   {
00304   }
00305 
00306   template<typename T>
00307     bool operator()(const T* const c_p1, 
00308                     const T* const c_p2, 
00309                     const T* const point, 
00310                     T* resid) const
00311     {
00312 
00314       int q = 0; 
00315       const T& ax = c_p1[q++]; 
00316       const T& ay = c_p1[q++]; 
00317       const T& az = c_p1[q++]; 
00318       const T& tx = c_p1[q++]; 
00319       const T& ty = c_p1[q++]; 
00320       const T& tz = c_p1[q++]; 
00322       q = 0; 
00323       const T& target_x = c_p2[q++]; 
00324       const T& target_y = c_p2[q++]; 
00325       const T& target_z = c_p2[q++]; 
00326       const T& target_ax = c_p2[q++]; 
00327       const T& target_ay = c_p2[q++]; 
00328       const T& target_az = c_p2[q++]; 
00331       // create a vector from the location of the point in the target's frame
00332       T point[3];
00333       point[0] = pnt_x_;
00334       point[1] = pnt_y_;
00335       point[2] = pnt_z_;
00336 
00338       T target_aa[3];
00339       T world_point_loc[3]; 
00340       target_aa[0] = target_ax;
00341       target_aa[1] = target_ay;
00342       target_aa[2] = target_az;
00343       ceres::AngleAxisRotatePoint(target_aa, point, world_point_loc);
00344 
00346       world_point_loc[0] = world_point_loc[0] + target_x;
00347       world_point_loc[1] = world_point_loc[1] + target_y;
00348       world_point_loc[2] = world_point_loc[2] + target_z;
00349 
00351       /*  Note that camera transform is from world into camera frame, not vise versa */
00352       T aa[3];
00353       T camera_point_loc[3]; 
00354       aa[0] = ax;
00355       aa[1] = ay;
00356       aa[2] = az;
00357       ceres::AngleAxisRotatePoint(aa, point, camera_point_loc);
00358 
00360       T xp1 = camera_point_loc[0] + tx; 
00361       T yp1 = camera_point_loc[1] + ty;
00362       T zp1 = camera_point_loc[2] + tz;
00363 
00365       T xp = xp1 / zp1;
00366       T yp = yp1 / zp1;
00367 
00369       resid[0] = T(fx_) * xp + T(cx_) - T(ox_);
00370       resid[1] = T(fy_) * yp + T(cy_) - T(oy_);
00371 
00372       return true;
00373     } 
00377   static ceres::CostFunction* Create(const double o_x, const double o_y, double fx, double fy, double cx, double cy)
00378   {
00379     return (new ceres::AutoDiffCostFunction<TargetCameraReprjErrorProjModelAsClassVars, 2, 6, 6, 3>(
00380         new CameraReprjError(o_x, o_y, fx, fy, cx, cy)));
00381   }
00382   double ox_; 
00383   double oy_; 
00384   double fx_; 
00385   double fy_; 
00386   double cx_; 
00387   double cy_; 
00388   double pnt_x_;
00389   double pnt_y_;
00390   double pnt_z_;
00391 };
00392 
00393 void printQTasH(double qx, double qy, double qz, double qw, double tx, double ty, double tz)
00394 {
00395   double Rs11 = qw * qw + qx * qx - qy * qy - qz * qz;
00396   double Rs21 = 2.0 * qx * qy + 2.0 * qw * qz;
00397   double Rs31 = 2.0 * qx * qz - 2.0 * qw * qy;
00398 
00399   double Rs12 = 2.0 * qx * qy - 2.0 * qw * qz;
00400   double Rs22 = qw * qw - qx * qx + qy * qy - qz * qz;
00401   double Rs32 = 2.0 * qy * qz + 2.0 * qw * qx;
00402 
00403   double Rs13 = 2.0 * qx * qz + 2.0 * qw * qy;
00404   double Rs23 = 2.0 * qy * qz - 2.0 * qw * qx;
00405   double Rs33 = qw * qw - qx * qx - qy * qy + qz * qz;
00406 
00407   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", Rs11, Rs12, Rs13, tx);
00408   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", Rs21, Rs22, Rs23, ty);
00409   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", Rs31, Rs32, Rs33, tz);
00410   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", 0.0, 0.0, 0.0, 1.0);
00411 }
00412 
00413 void printAATasH(double x, double y, double z, double tx, double ty, double tz)
00414 {
00415   double R[9];
00416   double aa[3];
00417   aa[0] = x;
00418   aa[1] = y;
00419   aa[2] = z;
00420   ceres::AngleAxisToRotationMatrix(aa, R);
00421   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", R[0], R[3], R[6], tx);
00422   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", R[1], R[4], R[7], ty);
00423   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", R[2], R[5], R[8], tz);
00424   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", 0.0, 0.0, 0.0, 1.0);
00425 }
00426 
00427 void printAATasHI(double x, double y, double z, double tx, double ty, double tz)
00428 {
00429   double R[9];
00430   double aa[3];
00431   aa[0] = x;
00432   aa[1] = y;
00433   aa[2] = z;
00434   ceres::AngleAxisToRotationMatrix(aa, R);
00435   double ix = -(tx * R[0] + ty * R[1] + tz * R[2]);
00436   double iy = -(tx * R[3] + ty * R[4] + tz * R[5]);
00437   double iz = -(tx * R[6] + ty * R[7] + tz * R[8]);
00438   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", R[0], R[1], R[2], ix);
00439   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", R[3], R[4], R[5], iy);
00440   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", R[6], R[7], R[8], iz);
00441   printf("%6.3lf %6.3lf %6.3lf %6.3lf\n", 0.0, 0.0, 0.0, 1.0);
00442 }
00443 
00444 void printAAasEuler(double x, double y, double z)
00445 {
00446   double R[9];
00447   double aa[3];
00448   aa[0] = x;
00449   aa[1] = y;
00450   aa[2] = z;
00451   ceres::AngleAxisToRotationMatrix(aa, R);
00452   double rx = atan2(R[7], R[8]);
00453   double ry = atan2(-R[6], sqrt(R[7] * R[7] + R[8] * R[8]));
00454   double rz = atan2(R[3], R[0]);
00455   printf("rpy = %8.4f %8.4f %8.4f\n", rx, ry, rz);
00456 }
00457 
00458 void printCameraParameters(CameraParameters C, std::string words)
00459 {
00460   printf("%s\n", words.c_str());
00461   printf("Camera to World Transform:\n");
00462   printAATasHI(C.aa[0], C.aa[1], C.aa[2], C.pos[0], C.pos[1], C.pos[2]);
00463 
00464   printf("World to Camera\n");
00465   printAATasH(C.aa[0], C.aa[1], C.aa[2], C.pos[0], C.pos[1], C.pos[2]);
00466   printAAasEuler(C.aa[0], C.aa[1], C.aa[2]);
00467   printf("fx = %8.3lf fy = %8.3lf\n", C.fx, C.fy);
00468   printf("k1 = %8.3lf k2 = %8.3lf k3 = %8.3lf\n", C.k1, C.k2, C.k3);
00469   printf("p1 = %8.3lf p2 = %8.3lf\n", C.p1, C.p2);
00470   printf("cx = %8.3lf cy = %8.3lf\n", C.cx, C.cy);
00471 }
00472 } // end of namespace


industrial_extrinsic_cal
Author(s): Chris Lewis
autogenerated on Wed Aug 26 2015 12:00:27