g2o
Loading...
Searching...
No Matches
types_icp.h
Go to the documentation of this file.
1// g2o - General Graph Optimization
2// Copyright (C) 2011 Kurt Konolige
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#ifndef G2O_TYPES_ICP
28#define G2O_TYPES_ICP
29
30#define GICP_ANALYTIC_JACOBIANS
31// #define SCAM_ANALYTIC_JACOBIANS
32
33#include <Eigen/Geometry>
34#include <iostream>
35
41#include "g2o_types_icp_api.h"
42
43namespace g2o {
44
45namespace types_icp {
46void init();
47}
48//
49// GICP-type edges
50// Each measurement is between two rigid points on each 6DOF vertex
51//
52
53//
54// class for edges between two points rigidly attached to vertices
55//
56
59
60 public:
61 // point positions
63
64 // unit normals
65 Vector3 normal0, normal1;
66
67 // rotation matrix for normal
69
70 // initialize an object
72 pos0.setZero();
73 pos1.setZero();
74 normal0 << 0, 0, 1;
75 normal1 << 0, 0, 1;
76 // makeRot();
77 R0.setIdentity();
78 R1.setIdentity();
79 }
80
81 // set up rotation matrix for pos0
82 void makeRot0() {
83 Vector3 y;
84 y << 0, 1, 0;
85 R0.row(2) = normal0;
86 y = y - normal0(1) * normal0;
87 y.normalize(); // need to check if y is close to 0
88 R0.row(1) = y;
89 R0.row(0) = normal0.cross(R0.row(1));
90 // cout << normal.transpose() << endl;
91 // cout << R0 << endl << endl;
92 // cout << R0*R0.transpose() << endl << endl;
93 }
94
95 // set up rotation matrix for pos1
96 void makeRot1() {
97 Vector3 y;
98 y << 0, 1, 0;
99 R1.row(2) = normal1;
100 y = y - normal1(1) * normal1;
101 y.normalize(); // need to check if y is close to 0
102 R1.row(1) = y;
103 R1.row(0) = normal1.cross(R1.row(1));
104 }
105
106 // returns a precision matrix for point-plane
107 Matrix3 prec0(double e) {
108 makeRot0();
109 Matrix3 prec;
110 prec << e, 0, 0, 0, e, 0, 0, 0, 1;
111 return R0.transpose() * prec * R0;
112 }
113
114 // returns a precision matrix for point-plane
115 Matrix3 prec1(double e) {
116 makeRot1();
117 Matrix3 prec;
118 prec << e, 0, 0, 0, e, 0, 0, 0, 1;
119 return R1.transpose() * prec * R1;
120 }
121
122 // return a covariance matrix for plane-plane
123 Matrix3 cov0(double e) {
124 makeRot0();
125 Matrix3 cov;
126 cov << 1, 0, 0, 0, 1, 0, 0, 0, e;
127 return R0.transpose() * cov * R0;
128 }
129
130 // return a covariance matrix for plane-plane
131 Matrix3 cov1(double e) {
132 makeRot1();
133 Matrix3 cov;
134 cov << 1, 0, 0, 0, 1, 0, 0, 0, e;
135 return R1.transpose() * cov * R1;
136 }
137};
138
139// 3D rigid constraint
140// 3 values for position wrt frame
141// 3 values for normal wrt frame, not used here
142// first two args are the measurement type, second two the connection classes
144 : public BaseBinaryEdge<3, EdgeGICP, VertexSE3, VertexSE3> {
145 public:
147 Edge_V_V_GICP() : pl_pl(false) {}
149
150 // switch to go between point-plane and plane-plane
151 bool pl_pl;
153
154 // I/O functions
155 virtual bool read(std::istream& is);
156 virtual bool write(std::ostream& os) const;
157
158 // return the error estimate as a 3-vector
160 // from <ViewPoint> to <Point>
161 const VertexSE3* vp0 = static_cast<const VertexSE3*>(_vertices[0]);
162 const VertexSE3* vp1 = static_cast<const VertexSE3*>(_vertices[1]);
163
164 // get vp1 point into vp0 frame
165 // could be more efficient if we computed this transform just once
166 Vector3 p1;
167
168#if 0
169 if (_cnum >= 0 && 0) // using global cache
170 {
171 if (_tainted[_cnum]) // set up transform
172 {
173 _transforms[_cnum] = vp0->estimate().inverse() * vp1->estimate();
174 _tainted[_cnum] = 0;
175 cout << _transforms[_cnum] << endl;
176 }
177 p1 = _transforms[_cnum].map(measurement().pos1); // do the transform
178 }
179 else
180#endif
181 {
182 p1 = vp1->estimate() * measurement().pos1;
183 p1 = vp0->estimate().inverse() * p1;
184 }
185
186 // cout << endl << "Error computation; points are: " << endl;
187 // cout << p0.transpose() << endl;
188 // cout << p1.transpose() << endl;
189
190 // get their difference
191 // this is simple Euclidean distance, for now
192 _error = p1 - measurement().pos0;
193
194#if 0
195 cout << "vp0" << endl << vp0->estimate() << endl;
196 cout << "vp1" << endl << vp1->estimate() << endl;
197 cout << "e Jac Xj" << endl << _jacobianOplusXj << endl << endl;
198 cout << "e Jac Xi" << endl << _jacobianOplusXi << endl << endl;
199#endif
200
201 if (!pl_pl) return;
202
203 // re-define the information matrix
204 // topLeftCorner<3,3>() is the rotation()
205 const Matrix3 transform = (vp0->estimate().inverse() * vp1->estimate())
206 .matrix()
207 .topLeftCorner<3, 3>();
208 information() = (cov0 + transform * cov1 * transform.transpose()).inverse();
209 }
210
211 // try analytic jacobians
212#ifdef GICP_ANALYTIC_JACOBIANS
213 virtual void linearizeOplus();
214#endif
215
216 // global derivative matrices
219 static Matrix3 dRidz; // differential quat matrices
220};
221
229 public:
230 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
231
232 VertexSCam();
233
234 // I/O
235 virtual bool read(std::istream& is);
236 virtual bool write(std::ostream& os) const;
237
238 // capture the update function to reset aux transforms
239 virtual void oplusImpl(const double* update) {
240 VertexSE3::oplusImpl(update);
241 setAll();
242 }
243
244 // camera matrix and stereo baseline
245 static Matrix3 Kcam;
246 static double baseline;
247
248 // transformations
249 Eigen::Matrix<double, 3, 4, Eigen::ColMajor>
250 w2n; // transform from world to node coordinates
251 Eigen::Matrix<double, 3, 4, Eigen::ColMajor>
252 w2i; // transform from world to image coordinates
253
254 // Derivatives of the rotation matrix transpose wrt quaternion xyz, used for
255 // calculating Jacobian wrt pose of a projection.
256 Matrix3 dRdx, dRdy, dRdz;
257
258 // transforms
259 static void transformW2F(Eigen::Matrix<double, 3, 4, Eigen::ColMajor>& m,
260 const Vector3& trans, const Quaternion& qrot) {
261 m.block<3, 3>(0, 0) = qrot.toRotationMatrix().transpose();
262 m.col(3).setZero(); // make sure there's no translation
263 Vector4 tt;
264 tt.head(3) = trans;
265 tt[3] = 1.0;
266 m.col(3) = -m * tt;
267 }
268
269 static void transformF2W(Eigen::Matrix<double, 3, 4, Eigen::ColMajor>& m,
270 const Vector3& trans, const Quaternion& qrot) {
271 m.block<3, 3>(0, 0) = qrot.toRotationMatrix();
272 m.col(3) = trans;
273 }
274
275 // set up camera matrix
276 static void setKcam(double fx, double fy, double cx, double cy, double tx) {
277 Kcam.setZero();
278 Kcam(0, 0) = fx;
279 Kcam(1, 1) = fy;
280 Kcam(0, 2) = cx;
281 Kcam(1, 2) = cy;
282 Kcam(2, 2) = 1.0;
283 baseline = tx;
284 }
285
286 // set transform from world to cam coords
288 w2n = estimate().inverse().matrix().block<3, 4>(0, 0);
289 // transformW2F(w2n,estimate().translation(), estimate().rotation());
290 }
291
292 // Set up world-to-image projection matrix (w2i), assumes camera parameters
293 // are filled.
294 void setProjection() { w2i = Kcam * w2n; }
295
296 // sets angle derivatives
297 void setDr() {
298 // inefficient, just for testing
299 // use simple multiplications and additions for production code in
300 // calculating dRdx,y,z for dS'*R', with dS the incremental change
301 dRdx = dRidx * w2n.block<3, 3>(0, 0);
302 dRdy = dRidy * w2n.block<3, 3>(0, 0);
303 dRdz = dRidz * w2n.block<3, 3>(0, 0);
304 }
305
306 // set all aux transforms
307 void setAll() {
308 setTransform();
309 setProjection();
310 setDr();
311 }
312
313 // calculate stereo projection
314 void mapPoint(Vector3& res, const Vector3& pt3) {
315 Vector4 pt;
316 pt.head<3>() = pt3;
317 pt(3) = cst(1.0);
318 Vector3 p1 = w2i * pt;
319 Vector3 p2 = w2n * pt;
320 Vector3 pb(baseline, 0, 0);
321
322 double invp1 = cst(1.0) / p1(2);
323 res.head<2>() = p1.head<2>() * invp1;
324
325 // right camera px
326 p2 = Kcam * (p2 - pb);
327 res(2) = p2(0) / p2(2);
328 }
329
333};
334
339// stereo projection
340// first two args are the measurement type, second two the connection classes
342 : public BaseBinaryEdge<3, Vector3, VertexPointXYZ, VertexSCam> {
343 public:
344 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
345
346 Edge_XYZ_VSC();
347
348 virtual bool read(std::istream& is);
349 virtual bool write(std::ostream& os) const;
350
351 // return the error estimate as a 2-vector
353 // from <Point> to <Cam>
354 const VertexPointXYZ* point =
355 static_cast<const VertexPointXYZ*>(_vertices[0]);
356 VertexSCam* cam = static_cast<VertexSCam*>(_vertices[1]);
357 // cam->setAll();
358
359 // calculate the projection
360 Vector3 kp;
361 cam->mapPoint(kp, point->estimate());
362
363 // std::cout << std::endl << "CAM " << cam->estimate() << std::endl;
364 // std::cout << "POINT " << pt.transpose() << std::endl;
365 // std::cout << "PROJ " << p1.transpose() << std::endl;
366 // std::cout << "PROJ " << p2.transpose() << std::endl;
367 // std::cout << "CPROJ " << kp.transpose() << std::endl;
368 // std::cout << "MEAS " << _measurement.transpose() << std::endl;
369
370 // error, which is backwards from the normal observed - calculated
371 // _measurement is the measured projection
372 _error = kp - _measurement;
373 }
374#ifdef SCAM_ANALYTIC_JACOBIANS
375 // jacobian
376 virtual void linearizeOplus();
377#endif
378};
379
380} // namespace g2o
381
382#endif // TYPES_ICP
const EstimateType & estimate() const
return the current estimate of the vertex
void makeRot0()
Definition types_icp.h:82
Matrix3 cov1(double e)
Definition types_icp.h:131
Matrix3 cov0(double e)
Definition types_icp.h:123
Vector3 pos0
Definition types_icp.h:62
Matrix3 prec0(double e)
Definition types_icp.h:107
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Definition types_icp.h:58
void makeRot1()
Definition types_icp.h:96
Matrix3 prec1(double e)
Definition types_icp.h:115
Matrix3 R0
Definition types_icp.h:68
Vector3 normal0
Definition types_icp.h:65
static Matrix3 dRidy
Definition types_icp.h:218
static Matrix3 dRidx
Definition types_icp.h:217
static Matrix3 dRidz
Definition types_icp.h:219
Point vertex, XYZ, is in types_sba.
Definition types_icp.h:342
Vertex for a tracked point in space.
Stereo camera vertex, derived from SE3 class. Note that we use the actual pose of the vertex as its p...
Definition types_icp.h:228
static void transformW2F(Eigen::Matrix< double, 3, 4, Eigen::ColMajor > &m, const Vector3 &trans, const Quaternion &qrot)
Definition types_icp.h:259
static Matrix3 dRidy
Definition types_icp.h:331
static Matrix3 dRidx
Definition types_icp.h:330
void setProjection()
Definition types_icp.h:294
static void transformF2W(Eigen::Matrix< double, 3, 4, Eigen::ColMajor > &m, const Vector3 &trans, const Quaternion &qrot)
Definition types_icp.h:269
virtual void oplusImpl(const double *update)
Definition types_icp.h:239
static double baseline
Definition types_icp.h:246
void setTransform()
Definition types_icp.h:287
static void setKcam(double fx, double fy, double cx, double cy, double tx)
Definition types_icp.h:276
Eigen::Matrix< double, 3, 4, Eigen::ColMajor > w2n
Definition types_icp.h:250
void mapPoint(Vector3 &res, const Vector3 &pt3)
Definition types_icp.h:314
Eigen::Matrix< double, 3, 4, Eigen::ColMajor > w2i
Definition types_icp.h:252
static Matrix3 dRidz
Definition types_icp.h:332
static Matrix3 Kcam
Definition types_icp.h:245
3D pose Vertex, represented as an Isometry3
Definition vertex_se3.h:50
#define G2O_TYPES_ICP_API
VectorN< 3 > Vector3
Definition eigen_types.h:51
MatrixN< 3 > Matrix3
Definition eigen_types.h:72
VectorN< 4 > Vector4
Definition eigen_types.h:52
constexpr double cst(long double v)
Definition misc.h:60
Eigen::Quaternion< double > Quaternion
Definition eigen_types.h:81
void transform(PlaneList &l, const SE3Quat &t)