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
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
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
00075 inf = inf * 100.0;
00076 }
00077 else
00078 {
00079
00080 inf = inf * matches;
00081 }
00082
00083 addEdge(from_idx, to_idx, eigenFromTf(association.a2b), inf);
00084 }
00085
00086
00087 printf("Optimizing...\n");
00088 optimizeGraph();
00089
00090
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
00100
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);
00114
00115
00116
00117
00118 g2o::VertexSE3 *vc = new g2o::VertexSE3();
00119 vc->estimate() = pose;
00120 vc->setId(vertex_idx);
00121
00122
00123 if (vertex_idx == 0)
00124 vc->setFixed(true);
00125
00126
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
00137
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
00151 g2o::SE3Quat transf(q,t);
00152
00153
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
00161 edge->setInformation(information_matrix);
00162
00163 optimizer.addEdge(edge);
00164 }
00165
00166 void KeyframeGraphSolverG2O::optimizeGraph()
00167 {
00168
00169 optimizer.initializeOptimization();
00170
00171
00172 optimizer.setUserLambdaInit(0.01);
00173
00174
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
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
00220 keyframe.pose = tfFromEigen(optimized_pose);
00221 }
00222 }
00223
00224 }