SO3 SO3 ::expAndTheta(const Vector3d & omega, double * theta) { *theta = omega.norm(); double half_theta = 0.5*(*theta); double imag_factor; double real_factor = cos(half_theta); if((*theta)<SMALL_EPS) { double theta_sq = (*theta)*(*theta); double theta_po4 = theta_sq*theta_sq; imag_factor = 0.5-0.0208333*theta_sq+0.000260417*theta_po4; } else { double sin_half_theta = sin(half_theta); imag_factor = sin_half_theta/(*theta); } return SO3(Quaterniond(real_factor, imag_factor*omega.x(), imag_factor*omega.y(), imag_factor*omega.z())); }
SO3 SO3 ::inverse() const { return SO3(unit_quaternion_.conjugate()); }
SO3 Sim3 ::so3() const { return SO3(quaternion()); }
void VisualOdometry::poseEstimationPnP() { // construct the 3d 2d observations vector<cv::Point3f> pts3d; vector<cv::Point2f> pts2d; for ( cv::DMatch m:feature_matches_ ) { pts3d.push_back( pts_3d_ref_[m.queryIdx] ); pts2d.push_back( keypoints_curr_[m.trainIdx].pt ); } Mat K = ( cv::Mat_<double>(3,3)<< ref_->camera_->fx_, 0, ref_->camera_->cx_, 0, ref_->camera_->fy_, ref_->camera_->cy_, 0,0,1 ); Mat rvec, tvec, inliers; cv::solvePnPRansac( pts3d, pts2d, K, Mat(), rvec, tvec, false, 100, 4.0, 0.99, inliers ); num_inliers_ = inliers.rows; cout<<"pnp inliers: "<<num_inliers_<<endl; T_c_r_estimated_ = SE3( SO3(rvec.at<double>(0,0), rvec.at<double>(1,0), rvec.at<double>(2,0)), Vector3d( tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0)) ); // using bundle adjustment to optimize the pose typedef g2o::BlockSolver<g2o::BlockSolverTraits<6,2>> Block; Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>(); Block* solver_ptr = new Block( linearSolver ); g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( solver_ptr ); g2o::SparseOptimizer optimizer; optimizer.setAlgorithm ( solver ); g2o::VertexSE3Expmap* pose = new g2o::VertexSE3Expmap(); pose->setId ( 0 ); pose->setEstimate ( g2o::SE3Quat ( T_c_r_estimated_.rotation_matrix(), T_c_r_estimated_.translation() ) ); optimizer.addVertex ( pose ); // edges for ( int i=0; i<inliers.rows; i++ ) { int index = inliers.at<int>(i,0); // 3D -> 2D projection EdgeProjectXYZ2UVPoseOnly* edge = new EdgeProjectXYZ2UVPoseOnly(); edge->setId(i); edge->setVertex(0, pose); edge->camera_ = curr_->camera_.get(); edge->point_ = Vector3d( pts3d[index].x, pts3d[index].y, pts3d[index].z ); edge->setMeasurement( Vector2d(pts2d[index].x, pts2d[index].y) ); edge->setInformation( Eigen::Matrix2d::Identity() ); optimizer.addEdge( edge ); } optimizer.initializeOptimization(); optimizer.optimize(10); T_c_r_estimated_ = SE3 ( pose->estimate().rotation(), pose->estimate().translation() ); }