refine_motion_estimate.cpp
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <iostream>
00003 #include <assert.h>
00004 
00005 #include "refine_motion_estimate.hpp"
00006 
00007 #define dump(v) std::cerr << #v << " : " << (v) << "\n"
00008 #define dumpT(v) std::cerr << #v << " : " << (v).transpose() << "\n"
00009 
00010 //#define dbg(...) fprintf(stderr, __VA_ARGS__)
00011 #define dbg(...)
00012 
00013 #define USE_ESM
00014 
00015 namespace fovis
00016 {
00017 
00018 static inline Eigen::Isometry3d
00019 isometryFromParams(const Eigen::Matrix<double, 6, 1>& params)
00020 {
00021   Eigen::Isometry3d result;
00022 
00023   double roll = params(3), pitch = params(4), yaw = params(5);
00024   double halfroll = roll / 2;
00025   double halfpitch = pitch / 2;
00026   double halfyaw = yaw / 2;
00027   double sin_r2 = sin(halfroll);
00028   double sin_p2 = sin(halfpitch);
00029   double sin_y2 = sin(halfyaw);
00030   double cos_r2 = cos(halfroll);
00031   double cos_p2 = cos(halfpitch);
00032   double cos_y2 = cos(halfyaw);
00033 
00034   Eigen::Quaterniond quat(
00035     cos_r2 * cos_p2 * cos_y2 + sin_r2 * sin_p2 * sin_y2,
00036     sin_r2 * cos_p2 * cos_y2 - cos_r2 * sin_p2 * sin_y2,
00037     cos_r2 * sin_p2 * cos_y2 + sin_r2 * cos_p2 * sin_y2,
00038     cos_r2 * cos_p2 * sin_y2 - sin_r2 * sin_p2 * cos_y2);
00039 
00040   result.setIdentity();
00041   result.translate(params.head<3>());
00042   result.rotate(quat);
00043 
00044   return result;
00045 }
00046 
00047 static inline Eigen::Matrix<double, 6, 1>
00048 isometryToParams(const Eigen::Isometry3d& M)
00049 {
00050   Eigen::Quaterniond q(M.rotation());
00051   double roll_a = 2 * (q.w()*q.x() + q.y()*q.z());
00052   double roll_b = 1 - 2 * (q.x()*q.x() + q.y()*q.y());
00053   double pitch_sin = 2 * (q.w()*q.y() - q.z()*q.x());
00054   double yaw_a = 2 * (q.w()*q.z() + q.x()*q.y());
00055   double yaw_b = 1 - 2 * (q.y()*q.y() + q.z()*q.z());
00056 
00057   Eigen::Matrix<double, 6, 1> result;
00058   result.head<3>() = M.translation();
00059   result(3) = atan2(roll_a, roll_b);
00060   result(4) = asin(pitch_sin);
00061   result(5) = atan2(yaw_a, yaw_b);
00062   return result;
00063 }
00064 
00065 static void
00066 computeReprojectionError(const Eigen::Matrix<double, 4, Eigen::Dynamic>& points,
00067     const Eigen::Matrix<double, 2, Eigen::Dynamic>& ref_projections,
00068     const Eigen::Matrix<double, 3, 4>& K,
00069     const Eigen::Isometry3d& motion,
00070     Eigen::VectorXd* err,
00071     int err_offset)
00072 {
00073   int num_points = points.cols();
00074   assert(((err->size() == num_points * 2) && (err_offset == 0)) || 
00075          ((err->size() == num_points * 4) && ((err_offset == 0) || (err_offset == num_points*2))));
00076   assert(num_points == ref_projections.cols());
00077 
00078   Eigen::Matrix<double, 3, 4> P = K * motion.matrix();
00079 
00080   for(int pind=0; pind < num_points; pind++) {
00081     Eigen::Vector3d uvw = P * points.col(pind);
00082     double u = uvw(0) / uvw(2);
00083     double v = uvw(1) / uvw(2);
00084     (*err)(err_offset + pind*2 + 0) = u - ref_projections(0, pind);
00085     (*err)(err_offset + pind*2 + 1) = v - ref_projections(1, pind);
00086   }
00087 }
00088 
00089 static void
00090 computeProjectionJacobian(const Eigen::Matrix<double, 6, 1>& params,
00091     double fx, double px, double py,
00092     const Eigen::Matrix<double, 4, Eigen::Dynamic>& points,
00093     Eigen::Matrix<double, Eigen::Dynamic, 6> *result,
00094     int result_row_offset)
00095 {
00096   double tx    = params(0);
00097   double ty    = params(1);
00098   double tz    = params(2);
00099   double roll  = params(3);
00100   double pitch = params(4);
00101   double yaw   = params(5);
00102   double sr   = sin(roll);
00103   double cr   = cos(roll);
00104   double sp   = sin(pitch);
00105   double cp   = cos(pitch);
00106   double sy   = sin(yaw);
00107   double cy   = cos(yaw);
00108 
00109   // projection matrix
00110   Eigen::Matrix<double, 3, 4> P;
00111   P << 
00112     fx*cp*cy - px*sp, px*cp*sr - fx*(cr*sy - cy*sp*sr), fx*(sr*sy + cr*cy*sp) + px*cp*cr, fx*tx + px*tz,
00113     fx*cp*sy - py*sp, fx*(cr*cy + sp*sr*sy) + py*cp*sr, py*cp*cr - fx*(cy*sr - cr*sp*sy), fx*ty + py*tz,
00114     -sp, cp*sr, cp*cr, tz;
00115 
00116   // Jacobian matrices for homogeneous coordinates of point projections
00117   // thank you matlab
00118   Eigen::Matrix<double, 6, 4> Ju, Jv, Jw;
00119   Ju << 0, 0, 0, fx,
00120      0, 0, 0, 0,
00121      0, 0, 0, px,
00122      0, fx*(sr*sy + cr*cy*sp) + px*cp*cr,   fx*(cr*sy - cy*sp*sr) - px*cp*sr, 0,
00123      - px*cp - fx*cy*sp, -sr*(px*sp - fx*cp*cy), -cr*(px*sp - fx*cp*cy), 0,
00124      -fx*cp*sy, - fx*cr*cy - fx*sp*sr*sy, fx*cy*sr - fx*cr*sp*sy, 0;
00125   Jv << 0, 0, 0, 0,
00126      0, 0, 0, fx,
00127      0, 0, 0, py,
00128      0, py*cp*cr - fx*(cy*sr - cr*sp*sy), - fx*(cr*cy + sp*sr*sy) - py*cp*sr, 0,
00129      - py*cp - fx*sp*sy, -sr*(py*sp - fx*cp*sy), -cr*(py*sp - fx*cp*sy), 0,
00130      fx*cp*cy,   fx*cy*sp*sr - fx*cr*sy, fx*sr*sy + fx*cr*cy*sp, 0;
00131   Jw << 0, 0, 0, 0,
00132      0, 0, 0, 0,
00133      0, 0, 0, 1,
00134      0, cp*cr, -cp*sr, 0,
00135      -cp, -sp*sr, -cr*sp, 0,
00136      0, 0, 0, 0;
00137 
00138   int num_points = points.cols();
00139 //  Eigen::Matrix<double, Eigen::Dynamic, 6> result(num_points*2, 6);
00140   assert(result->rows() == num_points*4 || result->rows() == num_points*2);
00141   assert(result->cols() == 6);
00142   assert(result_row_offset == 0);
00143   int row = 0;
00144   for(int i=0; i<num_points; i++) {
00145     const Eigen::Vector4d& point = points.col(i);
00146     Eigen::Vector3d uvw = P * point;
00147     Eigen::Matrix<double, 6, 1> du = Ju * point;
00148     Eigen::Matrix<double, 6, 1> dv = Jv * point;
00149     Eigen::Matrix<double, 6, 1> dw = Jw * point;
00150 
00151     double w_inv_sq = 1 / (uvw(2) * uvw(2));
00152 
00153     result->row(result_row_offset + row) = (du * uvw(2) - dw * uvw(0)) * w_inv_sq;
00154     result->row(result_row_offset + row+1) = (dv * uvw(2) - dw * uvw(1)) * w_inv_sq;
00155 
00156     row += 2;
00157   }
00158 }
00159 
00160 Eigen::Isometry3d 
00161 refineMotionEstimate(const Eigen::Matrix<double, 4, Eigen::Dynamic>& points, 
00162         const Eigen::Matrix<double, 2, Eigen::Dynamic>& ref_projections,
00163         double fx, double px, double py,
00164         const Eigen::Isometry3d& initial_estimate,
00165         int max_iterations)
00166 {
00167   Eigen::Matrix<double, 3, 4> xyz_c_to_uvw_c;
00168   xyz_c_to_uvw_c << fx, 0, px, 0,
00169                  0, fx, py, 0,
00170                  0, 0, 1, 0;
00171 
00172   Eigen::Isometry3d estimate = initial_estimate;
00173   Eigen::Matrix<double, 6, 1> estimate_vec = isometryToParams(estimate);
00174 
00175   int num_points = points.cols();
00176 
00177   // compute initial reprojection error
00178   Eigen::VectorXd err(num_points*2);
00179   computeReprojectionError(points, ref_projections, xyz_c_to_uvw_c, estimate, 
00180       &err, 0);
00181 
00182   double initial_sse = err.cwiseProduct(err).sum();
00183   double final_sse = initial_sse;
00184   dbg("T0 : [%7.3f %7.3f %7.3f] R: [%7.3f %7.3f %7.3f] E: %f\n", 
00185       estimate_vec(0), estimate_vec(1), estimate_vec(2), 
00186       estimate_vec(3), estimate_vec(4), estimate_vec(5), final_sse);
00187 
00188 //  // TODO use a non-zero lambda value for actual levenberg-marquadt refinement
00189 //  double lambda = 0;
00190 
00191   Eigen::Matrix<double, Eigen::Dynamic, 6> M(num_points*2, 6);
00192 
00193   for(int iter_num=0; iter_num<max_iterations; iter_num++) {
00194     computeProjectionJacobian(estimate_vec, fx, px, py, points, &M, 0);
00195 
00196     // Gauss-Newton:
00197     //    delta = -(pseudoinverse of M) * error
00198     //          = - inv(M'*M) * M' * error
00199     // Levenberg-Marquadt
00200     //    delta = - inv(M'*M + lambda * diag(M'*M)) * M' * error
00201 
00202     Eigen::Matrix<double, 6, 1> g = M.transpose() * err;
00203     Eigen::Matrix<double, 6, 6> MtM = M.transpose() * M;
00204 //    Eigen::Matrix<double, 6, 6> diag(MtM.diagonal().asDiagonal());
00205 //    MtM += lambda * diag;
00206     Eigen::Matrix<double, 6, 1> delta = - MtM.inverse() * g;
00207 
00208     // compute new isometry estimate
00209     Eigen::Matrix<double, 6, 1> next_params = estimate_vec + delta;
00210     Eigen::Isometry3d next_estimate = isometryFromParams(next_params);
00211 
00212     // compute reprojection error at new estimate
00213     computeReprojectionError(points, ref_projections, xyz_c_to_uvw_c, next_estimate, 
00214         &err, 0);
00215     double sse = err.cwiseProduct(err).sum();
00216     //std::cerr << iter_num << ": " << next_params.transpose() << " : " << sse << std::endl;
00217 
00218     // if stepping would increase the error, then just give up.
00219     if(sse > final_sse)
00220       break;
00221 
00222     // update estimate parameters and error values
00223     estimate_vec = next_params;
00224     estimate = next_estimate;
00225     final_sse = sse;
00226 
00227     // stop if we're not moving that much
00228     if(fabs(delta(0)) < 0.0001 &&
00229        fabs(delta(1)) < 0.0001 &&
00230        fabs(delta(2)) < 0.0001 &&
00231        fabs(delta(3)) < (0.01 * M_PI/180) &&
00232        fabs(delta(4)) < (0.01 * M_PI/180) &&
00233        fabs(delta(5)) < (0.01 * M_PI/180))
00234         break;
00235 
00236     dbg("T%-2d: [%7.3f %7.3f %7.3f] R: [%7.3f %7.3f %7.3f] E: %f\n", 
00237         iter_num+1,
00238         estimate_vec(0), estimate_vec(1), estimate_vec(2), 
00239         estimate_vec(3), estimate_vec(4), estimate_vec(5), final_sse);
00240   }
00241   dbg("T--: [%7.3f %7.3f %7.3f] R: [%7.3f %7.3f %7.3f] E: %f\n", 
00242       estimate_vec(0), estimate_vec(1), estimate_vec(2), 
00243       estimate_vec(3), estimate_vec(4), estimate_vec(5), final_sse);
00244 
00245   return estimate;
00246 }
00247 
00248 // ============= bidirectional reprojection error minimization ============
00249 
00250 static void
00251 computeReverseProjectionJacobian(const Eigen::Matrix<double, 6, 1>& params,
00252     double fx, double px, double py,
00253     const Eigen::Matrix<double, 4, Eigen::Dynamic>& points,
00254     Eigen::Matrix<double, Eigen::Dynamic, 6>* result,
00255     int result_row_offset)
00256 {
00257   double tx    = params(0);
00258   double ty    = params(1);
00259   double tz    = params(2);
00260   double roll  = params(3);
00261   double pitch = params(4);
00262   double yaw   = params(5);
00263   double sr   = sin(roll);
00264   double cr   = cos(roll);
00265   double sp   = sin(pitch);
00266   double cp   = cos(pitch);
00267   double sy   = sin(yaw);
00268   double cy   = cos(yaw);
00269 
00270   // Reverse projection matrix.  Thank you matlab.
00271   Eigen::Matrix<double, 3, 4> P;
00272   P << px*(sr*sy + cr*cy*sp) + fx*cp*cy, 
00273        fx*cp*sy - px*(cy*sr - cr*sp*sy), 
00274        px*cp*cr - fx*sp, 
00275        - px*(tx*(sr*sy + cr*cy*sp) - ty*(cy*sr - cr*sp*sy) + tz*cp*cr) - fx*(tx*cp*cy - tz*sp + ty*cp*sy),
00276 
00277        py*(sr*sy + cr*cy*sp) - fx*(cr*sy - cy*sp*sr), 
00278        fx*(cr*cy + sp*sr*sy) - py*(cy*sr - cr*sp*sy), 
00279        cp*(py*cr + fx*sr), 
00280        - py*(tx*(sr*sy + cr*cy*sp) - ty*(cy*sr - cr*sp*sy) + tz*cp*cr) - fx*(ty*(cr*cy + sp*sr*sy) - tx*(cr*sy - cy*sp*sr) + tz*cp*sr),
00281 
00282        sr*sy + cr*cy*sp, 
00283        cr*sp*sy - cy*sr, 
00284        cp*cr, 
00285        ty*(cy*sr - cr*sp*sy) - tx*(sr*sy + cr*cy*sp) - tz*cp*cr;
00286 
00287   // Jacobian matrices for homogeneous coordinates of reverse point projections
00288   // thank you matlab
00289   Eigen::Matrix<double, 6, 4> Ju, Jv, Jw;
00290   Ju << 0, 0, 0, - px*(sr*sy + cr*cy*sp) - fx*cp*cy,
00291         0, 0, 0, px*(cy*sr - cr*sp*sy) - fx*cp*sy,
00292         0, 0, 0, fx*sp - px*cp*cr,
00293         px*cr*sy - px*cy*sp*sr, - px*cr*cy - px*sp*sr*sy, -px*cp*sr, px*ty*(cr*cy + sp*sr*sy) - px*tx*(cr*sy - cy*sp*sr) + px*tz*cp*sr,
00294         -cy*(fx*sp - px*cp*cr), -sy*(fx*sp - px*cp*cr), - fx*cp - px*cr*sp, fx*(tz*cp + tx*cy*sp + ty*sp*sy) - px*(tx*cp*cr*cy - tz*cr*sp + ty*cp*cr*sy),
00295         px*(cy*sr - cr*sp*sy) - fx*cp*sy, px*(sr*sy + cr*cy*sp) + fx*cp*cy, 0, - fx*(ty*cp*cy - tx*cp*sy) - px*(tx*(cy*sr - cr*sp*sy) + ty*(sr*sy + cr*cy*sp));
00296 
00297  Jv << 0, 0, 0, fx*(cr*sy - cy*sp*sr) - py*(sr*sy + cr*cy*sp),
00298        0, 0, 0, py*(cy*sr - cr*sp*sy) - fx*(cr*cy + sp*sr*sy),
00299        0, 0, 0, -cp*(py*cr + fx*sr),
00300        fx*(sr*sy + cr*cy*sp) + py*(cr*sy - cy*sp*sr), - fx*(cy*sr - cr*sp*sy) - py*(cr*cy + sp*sr*sy), cp*(fx*cr - py*sr), py*(ty*(cr*cy + sp*sr*sy) - tx*(cr*sy - cy*sp*sr) + tz*cp*sr) - fx*(tx*(sr*sy + cr*cy*sp) - ty*(cy*sr - cr*sp*sy) + tz*cp*cr),
00301        cp*cy*(py*cr + fx*sr), cp*sy*(py*cr + fx*sr), -sp*(py*cr + fx*sr), -(py*cr + fx*sr)*(tx*cp*cy - tz*sp + ty*cp*sy),
00302        py*(cy*sr - cr*sp*sy) - fx*(cr*cy + sp*sr*sy), py*(sr*sy + cr*cy*sp) - fx*(cr*sy - cy*sp*sr), 0, fx*(tx*(cr*cy + sp*sr*sy) + ty*(cr*sy - cy*sp*sr)) - py*(tx*(cy*sr - cr*sp*sy) + ty*(sr*sy + cr*cy*sp));
00303 
00304   Jw << 0, 0, 0, - sr*sy - cr*cy*sp,
00305         0, 0, 0, cy*sr - cr*sp*sy,
00306         0, 0, 0, -cp*cr,
00307         cr*sy - cy*sp*sr, - cr*cy - sp*sr*sy, -cp*sr, ty*(cr*cy + sp*sr*sy) - tx*(cr*sy - cy*sp*sr) + tz*cp*sr,
00308         cp*cr*cy, cp*cr*sy, -cr*sp, -cr*(tx*cp*cy - tz*sp + ty*cp*sy),
00309         cy*sr - cr*sp*sy, sr*sy + cr*cy*sp, 0, - tx*(cy*sr - cr*sp*sy) - ty*(sr*sy + cr*cy*sp);
00310        
00311   int num_points = points.cols();
00312   assert(result->rows() == num_points*4 || result->rows() == num_points*2);
00313   assert(result->cols() == 6);
00314   assert(result_row_offset == 0 || result_row_offset == (result->rows() / 2));
00315 //  Eigen::Matrix<double, Eigen::Dynamic, 6> result(num_points*2, 6);
00316   int row = 0;
00317   for(int i=0; i<num_points; i++) {
00318     const Eigen::Vector4d& point = points.col(i);
00319     Eigen::Vector3d uvw = P * point;
00320     Eigen::Matrix<double, 6, 1> du = Ju * point;
00321     Eigen::Matrix<double, 6, 1> dv = Jv * point;
00322     Eigen::Matrix<double, 6, 1> dw = Jw * point;
00323 
00324     double w_inv_sq = 1 / (uvw(2) * uvw(2));
00325 
00326     result->row(result_row_offset + row) = (du * uvw(2) - dw * uvw(0)) * w_inv_sq;
00327     result->row(result_row_offset + row+1) = (dv * uvw(2) - dw * uvw(1)) * w_inv_sq;
00328 
00329     row += 2;
00330   }
00331 }
00332 
00333 void refineMotionEstimateBidirectional(const Eigen::Matrix<double, 4, Eigen::Dynamic>& ref_points, 
00334         const Eigen::Matrix<double, 2, Eigen::Dynamic>& ref_projections,
00335         const Eigen::Matrix<double, 4, Eigen::Dynamic>& target_points, 
00336         const Eigen::Matrix<double, 2, Eigen::Dynamic>& target_projections,
00337         double fx, 
00338         double px, double py,
00339         const Eigen::Isometry3d& initial_estimate,
00340         int max_iterations,
00341         Eigen::Isometry3d* result,
00342         Eigen::MatrixXd* result_covariance)
00343 {
00344   Eigen::Matrix<double, 3, 4> xyz_c_to_uvw_c;
00345   xyz_c_to_uvw_c << fx, 0, px, 0,
00346                  0, fx, py, 0,
00347                  0, 0, 1, 0;
00348 
00349   Eigen::Matrix<double, 6, 1> estimate_vec = isometryToParams(initial_estimate);
00350 
00351   int num_points = target_points.cols();
00352 
00353   // allocate space for reprojection error vector
00354   Eigen::VectorXd err(num_points*4);
00355   // reprojection error from target point cloud to reference image
00356   computeReprojectionError(target_points, ref_projections, xyz_c_to_uvw_c, 
00357       initial_estimate, &err, 0);
00358   // reprojection error from reference point cloud to target image
00359   computeReprojectionError(ref_points, target_projections, xyz_c_to_uvw_c, 
00360       initial_estimate.inverse(), &err, num_points*2);
00361 
00362 #ifdef USE_ESM
00363   // is this the jacobian at true minimum?
00364   Eigen::Matrix<double, Eigen::Dynamic, 6> M_0(num_points*4, 6);
00365   Eigen::Matrix<double, 6, 1> zero_vec;
00366   zero_vec.setZero();
00367   computeProjectionJacobian(zero_vec, fx, px, py, ref_points, &M_0, 0);
00368   computeReverseProjectionJacobian(zero_vec, fx, px, py, target_points, &M_0, num_points*2);
00369 #endif
00370 
00371   double initial_sse = err.cwiseProduct(err).sum();
00372   double final_sse = initial_sse;
00373   dbg("T0 : [%7.3f %7.3f %7.3f] R: [%7.3f %7.3f %7.3f] E: %f\n", 
00374       estimate_vec(0), estimate_vec(1), estimate_vec(2), 
00375       estimate_vec(3), estimate_vec(4), estimate_vec(5), final_sse);
00376 
00377   Eigen::Matrix<double, Eigen::Dynamic, 6> M(num_points * 4, 6);
00378 
00379   for(int iter_num=0; iter_num<max_iterations; iter_num++) {
00380     // jacobian of target point cloud projected on to reference image
00381     computeProjectionJacobian(estimate_vec, fx, px, py, target_points, &M, 0);
00382 
00383     // jacobian of reference point cloud projected on to target image
00384     computeReverseProjectionJacobian(estimate_vec, fx, px, py, ref_points, &M, num_points*2);
00385 
00386 #ifdef USE_ESM
00387     // ESM:
00388     //    delta = - 2 * pseudoinverse(M + M_0) * error
00389     M += M_0;
00390     Eigen::Matrix<double, 6, 1> g = M.transpose() * err;
00391     Eigen::Matrix<double, 6, 6> MtM = M.transpose() * M;
00392     Eigen::Matrix<double, 6, 1> delta = - 2 * MtM.inverse() * g;
00393 #else
00394     // Gauss-Newton:
00395     //    delta = -(pseudoinverse of M) * error
00396     //          = - inv(M'*M) * M' * error
00397     Eigen::Matrix<double, 6, 1> g = M.transpose() * err;
00398     Eigen::Matrix<double, 6, 6> MtM = M.transpose() * M;
00399     Eigen::Matrix<double, 6, 1> delta = - MtM.inverse() * g;
00400 #endif
00401 
00402     // compute new isometry estimate
00403     Eigen::Matrix<double, 6, 1> next_params = estimate_vec + delta;
00404     Eigen::Isometry3d next_estimate = isometryFromParams(next_params);
00405 
00406     // compute reprojection error at new estimate
00407     computeReprojectionError(target_points, ref_projections, xyz_c_to_uvw_c, next_estimate, 
00408         &err, 0);
00409     computeReprojectionError(ref_points, target_projections, xyz_c_to_uvw_c, next_estimate.inverse(), 
00410         &err, num_points*2);
00411     double sse = err.cwiseProduct(err).sum();
00412     //std::cerr << iter_num << ": " << next_params.transpose() << " : " << sse << std::endl;
00413 
00414     // if stepping would increase the error, then just give up.
00415     if(sse > final_sse)
00416       break;
00417 
00418     // update estimate parameters and error values
00419     estimate_vec = next_params;
00420     final_sse = sse;
00421     *result = next_estimate;
00422 
00423     // stop if we're not moving that much
00424     if(fabs(delta(0)) < 0.0001 &&
00425        fabs(delta(1)) < 0.0001 &&
00426        fabs(delta(2)) < 0.0001 &&
00427        fabs(delta(3)) < (0.01 * M_PI/180) &&
00428        fabs(delta(4)) < (0.01 * M_PI/180) &&
00429        fabs(delta(5)) < (0.01 * M_PI/180))
00430         break;
00431 
00432     dbg("T%-2d: [%7.3f %7.3f %7.3f] R: [%7.3f %7.3f %7.3f] E: %f\n", 
00433         iter_num+1,
00434         estimate_vec(0), estimate_vec(1), estimate_vec(2), 
00435         estimate_vec(3), estimate_vec(4), estimate_vec(5), final_sse);
00436   }
00437   dbg("T--: [%7.3f %7.3f %7.3f] R: [%7.3f %7.3f %7.3f] E: %f\n", 
00438       estimate_vec(0), estimate_vec(1), estimate_vec(2), 
00439       estimate_vec(3), estimate_vec(4), estimate_vec(5), final_sse);
00440 
00441   // compute the motion estimate covariance.
00442   //
00443   // XXX: this assumes that the covariance of the target feature locations is
00444   // identity.  In the future, we should allow the user to pass in a covariance
00445   // matrix on the feature locations (or at least specify a covariance for each
00446   // feature), which would then factor into this covariance matrix computation
00447   // here.
00448   if(result_covariance) {
00449     computeProjectionJacobian(estimate_vec, fx, px, py, target_points, &M, 0);
00450     computeReverseProjectionJacobian(estimate_vec, fx, px, py, ref_points, &M, num_points*2);
00451 #ifdef USE_ESM
00452     M += M_0;
00453     Eigen::Matrix<double, 6, 6> MtM_inv = (M.transpose() * M).inverse();
00454     *result_covariance = 4 * MtM_inv;
00455 #else
00456     Eigen::Matrix<double, 6, 6> MtM_inv = (M.transpose() * M).inverse();
00457     *result_covariance = MtM_inv;
00458 #endif
00459   }
00460 }
00461 
00462 }


libfovis
Author(s): Albert Huang, Maurice Fallon
autogenerated on Thu Jun 6 2019 20:16:12