00001
00024 #include "rgbdtools/graph/keyframe_graph_solver_g2o.h"
00025
00026 namespace rgbdtools {
00027
00028 KeyframeGraphSolverG2O::KeyframeGraphSolverG2O():
00029 KeyframeGraphSolver(),
00030 vertexIdx(0)
00031 {
00032 typedef g2o::BlockSolver< g2o::BlockSolverTraits<-1, -1> > SlamBlockSolver;
00033 typedef g2o::LinearSolverCSparse<SlamBlockSolver::PoseMatrixType> SlamLinearSolver;
00034
00035 linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolver_6_3::PoseMatrixType>();
00036 solver_ptr = new g2o::BlockSolver_6_3(linearSolver);
00037 g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
00038
00039 optimizer.setAlgorithm(solver);
00040 optimizer.setVerbose(true);
00041 }
00042
00043 KeyframeGraphSolverG2O::~KeyframeGraphSolverG2O()
00044 {
00045
00046 }
00047
00048 void KeyframeGraphSolverG2O::solve(
00049 KeyframeVector& keyframes,
00050 const KeyframeAssociationVector& associations,
00051 AffineTransformVector& path)
00052 {
00053
00054 printf("Adding vertices...\n");
00055 for (unsigned int p_idx = 0; p_idx < path.size(); ++p_idx)
00056 {
00057 addVertex(path[p_idx], p_idx);
00058 }
00059
00060
00061 printf("Adding VO edges...\n");
00062
00063 if(path.size() > 1)
00064 {
00065 InformationMatrix path_inf = InformationMatrix::Identity();
00066
00067 for (unsigned int p_idx = 0; p_idx < path.size()-1; ++p_idx)
00068 {
00069 int from_idx = p_idx;
00070 int to_idx = p_idx+1;
00071
00072 const AffineTransform& from_pose = path[from_idx];
00073 const AffineTransform& to_pose = path[to_idx];
00074
00075 AffineTransform tf = from_pose.inverse() * to_pose;
00076
00077 InformationMatrix inf = path_inf * 100.0;
00078 addEdge(from_idx, to_idx, tf, inf);
00079 }
00080 }
00081
00082 printf("Adding RANSAC edges...\n");
00083 InformationMatrix ransac_inf = InformationMatrix::Identity();
00084
00085 for (unsigned int as_idx = 0; as_idx < associations.size(); ++as_idx)
00086 {
00087 const KeyframeAssociation& association = associations[as_idx];
00088
00089
00090 if (association.type != KeyframeAssociation::RANSAC) continue;
00091
00092
00093 int kf_from_idx = association.kf_idx_a;
00094 int kf_to_idx = association.kf_idx_b;
00095
00096
00097 int from_idx = keyframes[kf_from_idx].index;
00098 int to_idx = keyframes[kf_to_idx].index;
00099
00100
00101 int n_matches = association.matches.size();
00102 InformationMatrix inf = ransac_inf;
00103
00104
00105 addEdge(from_idx, to_idx, association.a2b, inf);
00106 }
00107
00108
00109 printf("Optimizing...\n");
00110 optimizeGraph();
00111
00112
00113 printf("Updating path poses...\n");
00114 getOptimizedPoses(path);
00115
00116
00117 printf("Updating keyframe poses...\n");
00118 for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); ++kf_idx)
00119 {
00120 RGBDKeyframe& keyframe = keyframes[kf_idx];
00121 printf("keyframe.index: %d\n", keyframe.index);
00122 keyframe.pose = path[keyframe.index];
00123 }
00124 }
00125
00126 void KeyframeGraphSolverG2O::solve(
00127 KeyframeVector& keyframes,
00128 const KeyframeAssociationVector& associations)
00129 {
00130
00131 printf("Adding vertices...\n");
00132 for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); ++kf_idx)
00133 {
00134 const RGBDKeyframe& keyframe = keyframes[kf_idx];
00135 addVertex(keyframe.pose, kf_idx);
00136 }
00137
00138
00139 printf("Adding VO edges...\n");
00140
00141 InformationMatrix inf_identity = InformationMatrix::Identity();
00142
00143 for (unsigned int kf_idx = 0; kf_idx < keyframes.size()-1; ++kf_idx)
00144 {
00145 int from_idx = kf_idx;
00146 int to_idx = kf_idx+1;
00147
00148 const AffineTransform& from_pose = keyframes[from_idx].pose;
00149 const AffineTransform& to_pose = keyframes[to_idx].pose;
00150
00151 AffineTransform tf = from_pose.inverse() * to_pose;
00152
00153 InformationMatrix inf = inf_identity * 100.0;
00154 addEdge(from_idx, to_idx, tf, inf);
00155 }
00156
00157
00158 printf("Adding RANSAC edges...\n");
00159 for (unsigned int as_idx = 0; as_idx < associations.size(); ++as_idx)
00160 {
00161 const KeyframeAssociation& association = associations[as_idx];
00162 int from_idx = association.kf_idx_a;
00163 int to_idx = association.kf_idx_b;
00164
00165 int matches = association.matches.size();
00166 InformationMatrix inf = inf_identity * matches;
00167
00168 addEdge(from_idx, to_idx, association.a2b, inf);
00169 }
00170
00171
00172 printf("Optimizing...\n");
00173 optimizeGraph();
00174
00175
00176 printf("Updating keyframe poses...\n");
00177
00178 AffineTransformVector optimized_poses;
00179 optimized_poses.resize(keyframes.size());
00180 getOptimizedPoses(optimized_poses);
00181
00182 for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); ++kf_idx)
00183 {
00184 RGBDKeyframe& keyframe = keyframes[kf_idx];
00185 keyframe.pose = optimized_poses[kf_idx];
00186 }
00187 }
00188
00189 void KeyframeGraphSolverG2O::addVertex(
00190 const AffineTransform& vertex_pose,
00191 int vertex_idx)
00192 {
00193
00194
00195 double yaw,pitch,roll;
00196 yaw = atan2f(vertex_pose(1,0),vertex_pose(0,0));
00197 pitch = asinf(-vertex_pose(2,0));
00198 roll = atan2f(vertex_pose(2,1),vertex_pose(2,2));
00199
00200 g2o::Vector3d t(vertex_pose(0,3),vertex_pose(1,3),vertex_pose(2,3));
00201 g2o::Quaterniond q;
00202 q.x()=sin(roll/2)*cos(pitch/2)*cos(yaw/2)-cos(roll/2)*sin(pitch/2)*sin(yaw/2);
00203 q.y()=cos(roll/2)*sin(pitch/2)*cos(yaw/2)+sin(roll/2)*cos(pitch/2)*sin(yaw/2);
00204 q.z()=cos(roll/2)*cos(pitch/2)*sin(yaw/2)-sin(roll/2)*sin(pitch/2)*cos(yaw/2);
00205 q.w()=cos(roll/2)*cos(pitch/2)*cos(yaw/2)+sin(roll/2)*sin(pitch/2)*sin(yaw/2);
00206
00207 g2o::SE3Quat pose(q,t);
00208
00209
00210
00211
00212 g2o::VertexSE3 *vc = new g2o::VertexSE3();
00213 vc->setEstimate(pose);
00214
00215 vc->setId(vertex_idx);
00216
00217
00218 if (vertex_idx == 0)
00219 vc->setFixed(true);
00220
00221
00222 optimizer.addVertex(vc);
00223 }
00224
00225 void KeyframeGraphSolverG2O::addEdge(
00226 int from_idx,
00227 int to_idx,
00228 const AffineTransform& relative_pose,
00229 const Eigen::Matrix<double,6,6>& information_matrix)
00230 {
00231
00232
00233 double yaw,pitch,roll;
00234 yaw = atan2f(relative_pose(1,0),relative_pose(0,0));
00235 pitch = asinf(-relative_pose(2,0));
00236 roll = atan2f(relative_pose(2,1),relative_pose(2,2));
00237
00238 g2o::Vector3d t(relative_pose(0,3),relative_pose(1,3),relative_pose(2,3));
00239 g2o::Quaterniond q;
00240 q.x()=sin(roll/2)*cos(pitch/2)*cos(yaw/2)-cos(roll/2)*sin(pitch/2)*sin(yaw/2);
00241 q.y()=cos(roll/2)*sin(pitch/2)*cos(yaw/2)+sin(roll/2)*cos(pitch/2)*sin(yaw/2);
00242 q.z()=cos(roll/2)*cos(pitch/2)*sin(yaw/2)-sin(roll/2)*sin(pitch/2)*cos(yaw/2);
00243 q.w()=cos(roll/2)*cos(pitch/2)*cos(yaw/2)+sin(roll/2)*sin(pitch/2)*sin(yaw/2);
00244
00245
00246 g2o::SE3Quat transf(q,t);
00247
00248
00249
00250 g2o::EdgeSE3* edge = new g2o::EdgeSE3;
00251 edge->vertices()[0] = optimizer.vertex(from_idx);
00252 edge->vertices()[1] = optimizer.vertex(to_idx);
00253 edge->setMeasurement(transf);
00254
00255
00256 edge->setInformation(information_matrix);
00257
00258 optimizer.addEdge(edge);
00259 }
00260
00261 void KeyframeGraphSolverG2O::optimizeGraph()
00262 {
00263
00264 optimizer.initializeOptimization();
00265
00266
00267
00268
00269
00270 optimizer.optimize(20);
00271 }
00272
00273 void KeyframeGraphSolverG2O::getOptimizedPoses(AffineTransformVector& poses)
00274 {
00275 for (unsigned int idx = 0; idx < poses.size(); ++idx)
00276 {
00277
00278 g2o::VertexSE3* vertex = dynamic_cast<g2o::VertexSE3*>(optimizer.vertex(idx));
00279 double optimized_pose_quat[7];
00280 vertex->getEstimateData(optimized_pose_quat);
00281
00282 AffineTransform optimized_pose;
00283 double qx,qy,qz,qr,qx2,qy2,qz2,qr2;
00284
00285 qx=optimized_pose_quat[3];
00286 qy=optimized_pose_quat[4];
00287 qz=optimized_pose_quat[5];
00288 qr=optimized_pose_quat[6];
00289 qx2=qx*qx;
00290 qy2=qy*qy;
00291 qz2=qz*qz;
00292 qr2=qr*qr;
00293
00294 optimized_pose(0,0)=qr2+qx2-qy2-qz2;
00295 optimized_pose(0,1)=2*(qx*qy-qr*qz);
00296 optimized_pose(0,2)=2*(qz*qx+qr*qy);
00297 optimized_pose(0,3)=optimized_pose_quat[0];
00298 optimized_pose(1,0)=2*(qx*qy+qr*qz);
00299 optimized_pose(1,1)=qr2-qx2+qy2-qz2;
00300 optimized_pose(1,2)=2*(qy*qz-qr*qx);
00301 optimized_pose(1,3)=optimized_pose_quat[1];
00302 optimized_pose(2,0)=2*(qz*qx-qr*qy);
00303 optimized_pose(2,1)=2*(qy*qz+qr*qx);
00304 optimized_pose(2,2)=qr2-qx2-qy2+qz2;
00305 optimized_pose(2,3)=optimized_pose_quat[2];
00306
00307
00308 poses[idx] = optimized_pose;
00309 }
00310 }
00311
00312 }