keyframe_graph_solver_g2o.cpp
Go to the documentation of this file.
00001 
00024 #include "ccny_rgbd/mapping/keyframe_graph_solver_g2o.h"
00025 
00026 namespace ccny_rgbd {
00027 
00028 KeyframeGraphSolverG2O::KeyframeGraphSolverG2O(
00029   const ros::NodeHandle& nh,
00030   const ros::NodeHandle& nh_private):
00031   KeyframeGraphSolver(nh, nh_private),
00032   vertexIdx(0)
00033 {
00034   optimizer.setMethod(g2o::SparseOptimizer::LevenbergMarquardt);
00035   optimizer.setVerbose(false);
00036   
00037   linearSolver = new g2o::LinearSolverCholmod<g2o::BlockSolverX::PoseMatrixType>();
00038   solver_ptr = new g2o::BlockSolverX(&optimizer, linearSolver);
00039   
00040   optimizer.setSolver(solver_ptr);
00041 }
00042 
00043 KeyframeGraphSolverG2O::~KeyframeGraphSolverG2O()
00044 {
00045 
00046 }
00047 
00048 void KeyframeGraphSolverG2O::solve(
00049   KeyframeVector& keyframes,
00050   KeyframeAssociationVector& associations)
00051 {  
00052   // add vertices
00053   printf("Adding vertices...\n");
00054   for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); ++kf_idx)
00055   {
00056     const RGBDKeyframe& keyframe = keyframes[kf_idx];
00057     addVertex(eigenFromTf(keyframe.pose), kf_idx);   
00058   }
00059   
00060   // add edges
00061   printf("Adding edges...\n");
00062   for (unsigned int as_idx = 0; as_idx < associations.size(); ++as_idx)
00063   {
00064     const KeyframeAssociation& association = associations[as_idx];
00065     int from_idx = association.kf_idx_a;
00066     int to_idx   = association.kf_idx_b;
00067     
00068     int matches = association.matches.size();
00069     
00070     Eigen::Matrix<double,6,6> inf = Eigen::Matrix<double,6,6>::Identity();
00071     
00072     if (matches == 0)
00073     {
00074       // this is an odometry edge 
00075       inf = inf * 100.0;
00076     }
00077     else
00078     {
00079       // this is an SURF+RANSAC edge 
00080       inf = inf * matches;
00081     }
00082     
00083     addEdge(from_idx, to_idx, eigenFromTf(association.a2b), inf);
00084   }
00085   
00086   // run the optimization
00087   printf("Optimizing...\n");
00088   optimizeGraph();
00089   
00090   // update the poses
00091   printf("Updating poses...\n");
00092   updatePoses(keyframes);
00093 }
00094 
00095 void KeyframeGraphSolverG2O::addVertex(
00096   const Eigen::Matrix4f& vertex_pose,
00097   int vertex_idx)
00098 {
00099   // TODO: use eigen quaternion, not manual conversion 
00100   //Transform Eigen::Matrix4f into 3D traslation and rotation for g2o
00101   double yaw,pitch,roll; 
00102   yaw   = atan2f(vertex_pose(1,0),vertex_pose(0,0));
00103   pitch = asinf(-vertex_pose(2,0));
00104   roll  = atan2f(vertex_pose(2,1),vertex_pose(2,2));
00105 
00106   g2o::Vector3d t(vertex_pose(0,3),vertex_pose(1,3),vertex_pose(2,3));
00107   g2o::Quaterniond q;
00108   q.x()=sin(roll/2)*cos(pitch/2)*cos(yaw/2)-cos(roll/2)*sin(pitch/2)*sin(yaw/2);
00109   q.y()=cos(roll/2)*sin(pitch/2)*cos(yaw/2)+sin(roll/2)*cos(pitch/2)*sin(yaw/2);
00110   q.z()=cos(roll/2)*cos(pitch/2)*sin(yaw/2)-sin(roll/2)*sin(pitch/2)*cos(yaw/2);
00111   q.w()=cos(roll/2)*cos(pitch/2)*cos(yaw/2)+sin(roll/2)*sin(pitch/2)*sin(yaw/2);
00112 
00113   g2o::SE3Quat pose(q,t); // vertex pose
00114 
00115   // TODO: smart pointers
00116   
00117   // set up node
00118   g2o::VertexSE3 *vc = new g2o::VertexSE3();
00119   vc->estimate() = pose;
00120   vc->setId(vertex_idx);      
00121 
00122   // set first pose fixed
00123   if (vertex_idx == 0)
00124     vc->setFixed(true);
00125 
00126   // add to optimizer
00127   optimizer.addVertex(vc);
00128 }
00129 
00130 void KeyframeGraphSolverG2O::addEdge(
00131   int from_idx,
00132   int to_idx,
00133   const Eigen::Matrix4f& relative_pose,
00134   const Eigen::Matrix<double,6,6>& information_matrix)
00135 {
00136   // TODO: use eigen quaternion, not manual conversion 
00137   //Transform Eigen::Matrix4f into 3D traslation and rotation for g2o
00138   double yaw,pitch,roll;
00139   yaw   = atan2f(relative_pose(1,0),relative_pose(0,0));
00140   pitch = asinf(-relative_pose(2,0));
00141   roll  = atan2f(relative_pose(2,1),relative_pose(2,2));
00142 
00143   g2o::Vector3d t(relative_pose(0,3),relative_pose(1,3),relative_pose(2,3));
00144   g2o::Quaterniond q;
00145   q.x()=sin(roll/2)*cos(pitch/2)*cos(yaw/2)-cos(roll/2)*sin(pitch/2)*sin(yaw/2);
00146   q.y()=cos(roll/2)*sin(pitch/2)*cos(yaw/2)+sin(roll/2)*cos(pitch/2)*sin(yaw/2);
00147   q.z()=cos(roll/2)*cos(pitch/2)*sin(yaw/2)-sin(roll/2)*sin(pitch/2)*cos(yaw/2);
00148   q.w()=cos(roll/2)*cos(pitch/2)*cos(yaw/2)+sin(roll/2)*sin(pitch/2)*sin(yaw/2);
00149 
00150   // relative transformation
00151   g2o::SE3Quat transf(q,t); 
00152 
00153   // TODO: smart pointers
00154   
00155   g2o::EdgeSE3* edge = new g2o::EdgeSE3;
00156   edge->vertices()[0] = optimizer.vertex(from_idx);
00157   edge->vertices()[1] = optimizer.vertex(to_idx);
00158   edge->setMeasurement(transf);
00159 
00160   //Set the information matrix
00161   edge->setInformation(information_matrix);
00162 
00163   optimizer.addEdge(edge);
00164 }
00165 
00166 void KeyframeGraphSolverG2O::optimizeGraph()
00167 {
00168   //Prepare and run the optimization
00169   optimizer.initializeOptimization();
00170 
00171   //Set the initial Levenberg-Marquardt lambda
00172   optimizer.setUserLambdaInit(0.01);
00173 
00174   //Run optimization
00175   optimizer.optimize(10);
00176 }
00177 
00178 void KeyframeGraphSolverG2O::updatePoses(
00179   KeyframeVector& keyframes)
00180 {
00181   for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); ++kf_idx)
00182   {
00183     RGBDKeyframe& keyframe = keyframes[kf_idx];
00184     
00185     //Transform the vertex pose from G2O quaternion to Eigen::Matrix4f
00186     g2o::VertexSE3* vertex = dynamic_cast<g2o::VertexSE3*>(optimizer.vertex(kf_idx));
00187     double optimized_pose_quat[7];
00188     vertex->getEstimateData(optimized_pose_quat);
00189 
00190     Eigen::Matrix4f optimized_pose;
00191     double qx,qy,qz,qr,qx2,qy2,qz2,qr2;
00192 
00193     qx=optimized_pose_quat[3];
00194     qy=optimized_pose_quat[4];
00195     qz=optimized_pose_quat[5];
00196     qr=optimized_pose_quat[6];
00197     qx2=qx*qx;
00198     qy2=qy*qy;
00199     qz2=qz*qz;
00200     qr2=qr*qr;
00201 
00202     optimized_pose(0,0)=qr2+qx2-qy2-qz2;
00203     optimized_pose(0,1)=2*(qx*qy-qr*qz);
00204     optimized_pose(0,2)=2*(qz*qx+qr*qy);
00205     optimized_pose(0,3)=optimized_pose_quat[0];
00206     optimized_pose(1,0)=2*(qx*qy+qr*qz);
00207     optimized_pose(1,1)=qr2-qx2+qy2-qz2;
00208     optimized_pose(1,2)=2*(qy*qz-qr*qx);
00209     optimized_pose(1,3)=optimized_pose_quat[1];
00210     optimized_pose(2,0)=2*(qz*qx-qr*qy);
00211     optimized_pose(2,1)=2*(qy*qz+qr*qx);
00212     optimized_pose(2,2)=qr2-qx2-qy2+qz2;
00213     optimized_pose(2,3)=optimized_pose_quat[2];
00214     optimized_pose(3,0)=0;
00215     optimized_pose(3,1)=0;
00216     optimized_pose(3,2)=0;
00217     optimized_pose(3,3)=1;
00218 
00219     //Set the optimized pose to the vector of poses
00220     keyframe.pose = tfFromEigen(optimized_pose);
00221   }
00222 }
00223 
00224 } // namespace ccny_rgbd
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends


ccny_rgbd
Author(s): Ivan Dryanovski
autogenerated on Fri Apr 12 2013 20:38:48