00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef TYPES_ICP
00018 #define TYPES_ICP
00019
00020 #define GICP_ANALYTIC_JACOBIANS
00021
00022
00023 #include "g2o/core/base_vertex.h"
00024 #include "g2o/core/base_binary_edge.h"
00025 #include "g2o/core/base_multi_edge.h"
00026 #include "g2o/math_groups/sbacam.h"
00027 #include "g2o/types/sba/types_sba.h"
00028 #include "g2o/types/slam3d/types_six_dof_quat.h"
00029 #include <Eigen/Geometry>
00030 #include <iostream>
00031
00032 namespace g2o {
00033
00034 using namespace Eigen;
00035 using namespace std;
00036 typedef Matrix<double, 6, 1> Vector6d;
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 class EdgeGICP
00051 {
00052 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00053
00054 public:
00055
00056 Vector3d pos0, pos1;
00057
00058
00059 Vector3d normal0, normal1;
00060
00061
00062 Matrix3d R0,R1;
00063
00064
00065 EdgeGICP()
00066 {
00067 pos0.setZero();
00068 pos1.setZero();
00069 normal0 << 0, 0, 1;
00070 normal1 << 0, 0, 1;
00071
00072 R0.setIdentity();
00073 R1.setIdentity();
00074 }
00075
00076
00077 void makeRot0()
00078 {
00079 Vector3d y;
00080 y << 0, 1, 0;
00081 R0.row(2) = normal0;
00082 y = y - normal0(1)*normal0;
00083 y.normalize();
00084 R0.row(1) = y;
00085 R0.row(0) = normal0.cross(R0.row(1));
00086
00087
00088
00089 }
00090
00091
00092 void makeRot1()
00093 {
00094 Vector3d y;
00095 y << 0, 1, 0;
00096 R1.row(2) = normal1;
00097 y = y - normal1(1)*normal1;
00098 y.normalize();
00099 R1.row(1) = y;
00100 R1.row(0) = normal1.cross(R1.row(1));
00101 }
00102
00103
00104 Matrix3d prec0(double e)
00105 {
00106 makeRot0();
00107 Matrix3d prec;
00108 prec << e, 0, 0,
00109 0, e, 0,
00110 0, 0, 1;
00111 return R0.transpose()*prec*R0;
00112 }
00113
00114 };
00115
00116
00117
00118
00119
00120
00121 class Edge_V_V_GICP : public BaseBinaryEdge<3, EdgeGICP, VertexSE3, VertexSE3>
00122 {
00123 public:
00124 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00125 Edge_V_V_GICP() : pl_pl(false) {};
00126 Edge_V_V_GICP(const Edge_V_V_GICP* e);
00127
00128
00129 bool pl_pl;
00130 Matrix3d cov0, cov1;
00131
00132
00133 virtual bool read(std::istream& is);
00134 virtual bool write(std::ostream& os) const;
00135
00136
00137 void computeError()
00138 {
00139
00140 const VertexSE3 *vp0 = static_cast<const VertexSE3*>(_vertices[0]);
00141 const VertexSE3 *vp1 = static_cast<const VertexSE3*>(_vertices[1]);
00142
00143
00144
00145 Vector3d p1;
00146
00147 #if 0
00148 if (_cnum >= 0 && 0)
00149 {
00150 if (_tainted[_cnum])
00151 {
00152 _transforms[_cnum] = vp0->estimate().inverse() * vp1->estimate();
00153 _tainted[_cnum] = 0;
00154 cout << _transforms[_cnum] << endl;
00155 }
00156 p1 = _transforms[_cnum].map(measurement().pos1);
00157 }
00158 else
00159 #endif
00160 {
00161 p1 = vp1->estimate().map(measurement().pos1);
00162 p1 = vp0->estimate().inverse().map(p1);
00163 }
00164
00165
00166
00167
00168
00169
00170
00171 _error = p1 - measurement().pos0;
00172
00173 #if 0
00174 cout << "vp0" << endl << vp0->estimate() << endl;
00175 cout << "vp1" << endl << vp1->estimate() << endl;
00176 cout << "e Jac Xj" << endl << _jacobianOplusXj << endl << endl;
00177 cout << "e Jac Xi" << endl << _jacobianOplusXi << endl << endl;
00178 #endif
00179
00180 if (!pl_pl) return;
00181
00182
00183 const Matrix3d transform = ( vp0->estimate().inverse() * vp1->estimate() ).rotation().toRotationMatrix();
00184 information() = ( cov0 + transform * cov1 * transform.transpose() ).inverse();
00185
00186 }
00187
00188
00189 #ifdef GICP_ANALYTIC_JACOBIANS
00190 virtual void linearizeOplus();
00191 #endif
00192
00193
00194 static Matrix3d dRidx, dRidy, dRidz;
00195 };
00196
00197
00198
00207 class VertexSCam : public VertexSE3
00208 {
00209 public:
00210 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00211
00212 VertexSCam();
00213
00214
00215 virtual bool read(std::istream& is);
00216 virtual bool write(std::ostream& os) const;
00217
00218
00219 virtual void oplus(double* update)
00220 {
00221 VertexSE3::oplus(update);
00222 setAll();
00223 }
00224
00225
00226 static Matrix3d Kcam;
00227 static double baseline;
00228
00229
00230 Matrix<double,3,4> w2n;
00231 Matrix<double,3,4> w2i;
00232
00233
00234
00235 Matrix3d dRdx, dRdy, dRdz;
00236
00237
00238 static void transformW2F(Matrix<double,3,4> &m,
00239 const Vector3d &trans,
00240 const Quaterniond &qrot)
00241 {
00242 m.block<3,3>(0,0) = qrot.toRotationMatrix().transpose();
00243 m.col(3).setZero();
00244 Vector4d tt;
00245 tt.head(3) = trans;
00246 tt[3] = 1.0;
00247 m.col(3) = -m*tt;
00248 }
00249
00250 static void transformF2W(Matrix<double,3,4> &m,
00251 const Vector3d &trans,
00252 const Quaterniond &qrot)
00253 {
00254 m.block<3,3>(0,0) = qrot.toRotationMatrix();
00255 m.col(3) = trans;
00256 }
00257
00258
00259 static void setKcam(double fx, double fy, double cx, double cy, double tx)
00260 {
00261 Kcam.setZero();
00262 Kcam(0,0) = fx;
00263 Kcam(1,1) = fy;
00264 Kcam(0,2) = cx;
00265 Kcam(1,2) = cy;
00266 Kcam(2,2) = 1.0;
00267 baseline = tx;
00268 }
00269
00270
00271 void setTransform() { transformW2F(w2n,estimate().translation(),
00272 estimate().rotation()); }
00273
00274
00275
00276 void setProjection() { w2i = Kcam * w2n; }
00277
00278
00279 void setDr()
00280 {
00281
00282
00283
00284 dRdx = dRidx * w2n.block<3,3>(0,0);
00285 dRdy = dRidy * w2n.block<3,3>(0,0);
00286 dRdz = dRidz * w2n.block<3,3>(0,0);
00287 }
00288
00289
00290 void setAll()
00291 {
00292 setTransform();
00293 setProjection();
00294 setDr();
00295 }
00296
00297
00298 void mapPoint(Vector3d &res, const Vector3d &pt3)
00299 {
00300 Vector4d pt;
00301 pt.head<3>() = pt3;
00302 pt(3) = 1.0;
00303 Vector3d p1 = w2i * pt;
00304 Vector3d p2 = w2n * pt;
00305 Vector3d pb(baseline,0,0);
00306
00307 double invp1 = 1.0/p1(2);
00308 res.head<2>() = p1.head<2>()*invp1;
00309
00310
00311 p2 = Kcam*(p2-pb);
00312 res(2) = p2(0)/p2(2);
00313 }
00314
00315 static Matrix3d dRidx, dRidy, dRidz;
00316 };
00317
00318
00324
00325
00326 class Edge_XYZ_VSC : public BaseBinaryEdge<3, Vector3d, VertexPointXYZ, VertexSCam>
00327 {
00328 public:
00329 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00330
00331 Edge_XYZ_VSC();
00332
00333 virtual bool read(std::istream& is);
00334 virtual bool write(std::ostream& os) const;
00335
00336
00337 void computeError()
00338 {
00339
00340 const VertexPointXYZ *point = static_cast<const VertexPointXYZ*>(_vertices[0]);
00341 VertexSCam *cam = static_cast<VertexSCam*>(_vertices[1]);
00342
00343
00344
00345 Vector3d kp;
00346 cam->mapPoint(kp,point->estimate());
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 _error = kp - _measurement;
00358 }
00359 #ifdef SCAM_ANALYTIC_JACOBIANS
00360
00361 virtual void linearizeOplus();
00362 #endif
00363 };
00364
00365
00366
00367 }
00368
00369 #endif // TYPES_ICP