00001 #ifndef _TYPES_G2O_PTAM_
00002 #define _TYPES_G2O_PTAM_
00003
00004 #include <Eigen/StdVector>
00005 #include <tr1/random>
00006 #include <iostream>
00007 #include <stdint.h>
00008 #include <tr1/unordered_set>
00009
00010 #include "g2o/core/graph_optimizer_sparse.h"
00011 #include "g2o/core/block_solver.h"
00012 #include "g2o/core/solver.h"
00013 #include "g2o/solvers/cholmod/linear_solver_cholmod.h"
00014 #include "g2o/solvers/dense/linear_solver_dense.h"
00015 #include "g2o/core/structure_only_solver.h"
00016
00017 #include "g2o/core/base_vertex.h"
00018 #include "g2o/core/base_binary_edge.h"
00019 #include "g2o/core/base_multi_edge.h"
00020
00021 #include <Eigen/Eigen>
00022 #include <Eigen/Geometry>
00023
00024 #include <cstdio>
00025 #include <iostream>
00026 #include <fstream>
00027
00028 using namespace std;
00029
00030
00031
00032 typedef Eigen::Matrix<double, 2, 1> Vector2;
00033 typedef Eigen::Matrix<double, 3, 1> Vector3;
00034 typedef Eigen::Matrix<double, 4, 1> Vector4;
00035 typedef Eigen::Matrix<double, 5, 1> Vector5;
00036 typedef Eigen::Matrix<double, 6, 1> Vector6;
00037
00038 typedef Eigen::Matrix<double, 3, 3> Matrix3;
00039 typedef Eigen::Matrix<double, 4, 4> Matrix4;
00040 typedef Eigen::Matrix<double, 6, 6> Matrix6;
00041
00042
00043
00044 class SE3AxisAngle
00045 {
00046 public:
00047
00048
00049 SE3AxisAngle()
00050 {
00051 t.fill(0);
00052 axis.fill(0);
00053 }
00054
00056
00057 inline SE3AxisAngle(const Vector6 mu)
00058 {
00059 t = mu.segment<3>(0);
00060 axis = mu.segment<3>(3);
00061 }
00062
00064
00065 inline void setAxisAngle(const Vector6 mu)
00066 {
00067 t = mu.segment<3>(0);
00068 axis = mu.segment<3>(3);
00069 }
00070
00072
00073 SE3AxisAngle& operator=(const Matrix4& m)
00074 {
00075 Vector6 v6;
00076 v6 = log(m);
00077 t = v6.segment<3>(0);
00078 axis = v6.segment<3>(3);
00079 return *this;
00080 }
00081
00083
00084 Vector3 map(const Vector3& pto_xyz)
00085 {
00086 Matrix4 T;
00087 T = exp(getAxisAngle());
00088 return (T.block<3,3>(0,0) * pto_xyz) + T.block<3,1>(0,3);
00089 }
00090
00092
00093 Vector3 mapInv(const Vector3& pto_xyz)
00094 {
00095 Matrix4 T;
00096 T = exp(-getAxisAngle());
00097 return (T.block<3,3>(0,0) * pto_xyz) + T.block<3,1>(0,3);
00098 }
00099
00101
00102 Vector6 getAxisAngle(void)
00103 {
00104 Vector6 mu;
00105 mu.segment<3>(0) = t;
00106 mu.segment<3>(3) = axis;
00107 return(mu);
00108 }
00109
00111
00112 SE3AxisAngle inverse() { return SE3AxisAngle(log(exp(-getAxisAngle()))); }
00113
00114
00115 static Vector6 log(const Matrix4& m);
00116 static Matrix4 exp(const Vector6 & mu);
00117
00118
00119 private:
00120 Vector3 t, axis;
00121 };
00122
00123
00124
00129
00130
00131
00132 namespace g2o
00133 {
00134
00135 using namespace Eigen;
00136
00140 class VertexPointXYZ : public BaseVertex<3, Vector3>
00141 {
00142 public:
00143 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00144
00145 VertexPointXYZ() {}
00146
00148
00149 virtual bool read(std::istream& is) { return true; }
00150 virtual bool write(std::ostream& os) const { return true; }
00151
00153
00154 virtual void setToOrigin() { _estimate.fill(0.); }
00155
00157
00158 virtual void oplus(double* update_)
00159 {
00160
00161 for (int i=0; i<3; i++) _estimate[i] += update_[i];
00162
00163 }
00164 };
00165
00166
00169
00172 class VertexSE3AxisAngle : public BaseVertex<6, SE3AxisAngle>
00173 {
00174 public:
00175 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00176
00177 VertexSE3AxisAngle(Vector6 calibracion): K(calibracion)
00178 {
00179 Rcw = MatrixXd::Identity(3, 3);
00180 tcw = MatrixXd::Zero(3, 1);
00181 }
00182
00184
00185 VertexSE3AxisAngle(Vector6 calibracion, Vector6 mu, bool Twc = false)
00186 : K(calibracion)
00187 {
00188 Matrix4 upd;
00189 upd = SE3AxisAngle::exp(mu);
00190
00191 this->Twc = Twc;
00192 if(Twc)
00193 {
00194 Rcw = (upd.block<3,3>(0,0)).transpose();
00195 tcw = -Rcw * upd.block<3,1>(0,3);
00196 }else
00197 {
00198 Rcw = upd.block<3,3>(0,0);
00199 tcw = upd.block<3,1>(0,3);
00200 }
00201 }
00202
00204
00205 VertexSE3AxisAngle(Vector6 calibracion, Matrix4 T, bool Twc = false)
00206 : K(calibracion)
00207 {
00208 this->Twc = Twc;
00209 if(Twc)
00210 {
00211 Rcw = (T.block<3,3>(0,0)).transpose();
00212 tcw = -Rcw * T.block<3,1>(0,3);
00213 }else
00214 {
00215 Rcw = T.block<3,3>(0,0);
00216 tcw = T.block<3,1>(0,3);
00217 }
00218 }
00220
00221 bool read(std::istream& is) { return true; }
00222 bool write(std::ostream& os) const { return true; }
00223
00225
00226 virtual void setToOrigin() { _estimate = SE3AxisAngle(); }
00227
00229
00230 virtual void oplus(double* update_)
00231 {
00232 Vector6 update;
00233 Matrix4 upd;
00234 for (int i=0; i<6; i++) update[i] = update_[i];
00235
00236
00237 upd = SE3AxisAngle::exp(update);
00238 Rcw = upd.block<3,3>(0,0) * Rcw;
00239 tcw = upd.block<3,3>(0,0) * tcw + upd.block<3,1>(0,3);
00240 }
00241
00243
00244 Vector2d map(const Vector3 & Pw)
00245 {
00246 double fx, fy, cx, cy, k1, k2;
00247 cx = K(0);
00248 cy = K(1);
00249 fx = K(2);
00250 fy = K(3);
00251 k1 = K(4);
00252 k2 = K(5);
00253
00254 double r2, r4, L;
00255
00256 Vector3 Pc =Rcw * Pw + tcw;
00257 Vector2d proj; proj(0) = Pc(0)/Pc(2); proj(1) = Pc(1)/Pc(2);
00258 r2 = proj[0]*proj[0] + proj[1]*proj[1];
00259 r4 = r2*r2;
00260 L = 1 + k1*r2 + k2*r4;
00261
00262 Vector2d res;
00263 res[0] = cx + fx * L * proj[0];
00264 res[1] = cy + fy * L * proj[1];
00265 return res;
00266 }
00267
00269
00270 void push()
00271 {
00272 RtMatrix *upd;
00273 upd = new RtMatrix();
00274 upd->block<3,3>(0,0) = Rcw;
00275 upd->block<3,1>(0,3) = tcw;
00276 backups.push(upd);
00277 BaseVertex<6, SE3AxisAngle>::push();
00278 }
00279
00281
00282 void pop()
00283 {
00284 RtMatrix *upd;
00285 assert(!backups.empty());
00286 upd = backups.top();
00287 Rcw = upd->block<3,3>(0,0);
00288 tcw = upd->block<3,1>(0,3);
00289 backups.pop();
00290 delete upd;
00291 BaseVertex<6, SE3AxisAngle>::pop();
00292 }
00293
00295
00296 Matrix4 getCamera(bool Twc=false)
00297 {
00298 Vector6 cam;
00299 Matrix4 upd;
00300 upd.setIdentity();
00301 if(Twc)
00302 {
00303 upd.block<3,3>(0,0) = Rcw.transpose();
00304 upd.block<3,1>(0,3) = -upd.block<3,3>(0,0) * tcw;
00305 }else
00306 {
00307 upd.block<3,3>(0,0) = Rcw;
00308 upd.block<3,1>(0,3) = tcw;
00309 }
00310
00311
00312 return upd;
00313 }
00314
00315 private:
00316 typedef Matrix<double, 3, 4> RtMatrix;
00317
00318 std::stack<RtMatrix*> backups;
00319
00320
00321 bool Twc;
00322 Matrix3 Rcw;
00323 Vector3 tcw;
00324 Vector6 K;
00325 };
00326
00329
00330
00331 class EdgeProjectXYZ2UV : public BaseMultiEdge<2, Vector2d>
00332 {
00333 public:
00334 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00335
00336 EdgeProjectXYZ2UV(){resize(2);};
00337
00339
00340 bool read(std::istream& is){return true;};
00341 bool write(std::ostream& os) const{return true;};
00342
00344
00345 void computeError()
00346 {
00347 VertexSE3AxisAngle* cam =
00348 static_cast<const VertexSE3AxisAngle*>(_vertices[0]);
00349 VertexPointXYZ* pto =
00350 static_cast<const VertexPointXYZ*>(_vertices[1]);
00351
00352 Vector2d obs(_measurement);
00353 _error = obs - cam->map(pto->estimate());
00354 }
00355
00357
00358
00359
00360 };
00361
00362
00363 }
00364
00365
00366
00367 typedef struct
00368 {
00369 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00370
00371 Vector6 cal;
00372 Matrix4 cam;
00373 vector < Vector2, Eigen::aligned_allocator<Vector2> > pto2D;
00374 vector < Vector3, Eigen::aligned_allocator<Vector3> > pto3D;
00375 Matrix4 solMatlab;
00376 } Data;
00377
00378
00379 void poseOptimization(Data &dat);
00380
00381 #endif