g2o
Loading...
Searching...
No Matches
types_icp.cpp
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#include "types_icp.h"
28
29#include <iostream>
30
31#include "g2o/core/factory.h"
32#include "g2o/stuff/macros.h"
33
34using namespace Eigen;
35
36namespace g2o {
37
40
41namespace types_icp {
43
44void init() {
45 if (types_icp::initialized) return;
46 Edge_V_V_GICP::dRidx << 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, -2.0, 0.0;
47 Edge_V_V_GICP::dRidy << 0.0, 0.0, -2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0;
48 Edge_V_V_GICP::dRidz << 0.0, 2.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, 0.0;
49
50 VertexSCam::dRidx << 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, -2.0, 0.0;
51 VertexSCam::dRidy << 0.0, 0.0, -2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0;
52 VertexSCam::dRidz << 0.0, 2.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, 0.0;
53
55}
56} // namespace types_icp
57
58using namespace std;
59
60Matrix3 Edge_V_V_GICP::dRidx; // differential quat matrices
61Matrix3 Edge_V_V_GICP::dRidy; // differential quat matrices
62Matrix3 Edge_V_V_GICP::dRidz; // differential quat matrices
63Matrix3 VertexSCam::dRidx; // differential quat matrices
64Matrix3 VertexSCam::dRidy; // differential quat matrices
65Matrix3 VertexSCam::dRidz; // differential quat matrices
68
69// global initialization
71
72// Copy constructor
75 // Temporary hack - TODO, sort out const-ness properly
76 _vertices[0] = const_cast<HyperGraph::Vertex*>(e->vertex(0));
77 _vertices[1] = const_cast<HyperGraph::Vertex*>(e->vertex(1));
78
79 _measurement.pos0 = e->measurement().pos0;
80 _measurement.pos1 = e->measurement().pos1;
81 _measurement.normal0 = e->measurement().normal0;
82 _measurement.normal1 = e->measurement().normal1;
83 _measurement.R0 = e->measurement().R0;
84 _measurement.R1 = e->measurement().R1;
85
86 pl_pl = e->pl_pl;
87 cov0 = e->cov0;
88 cov1 = e->cov1;
89
90 // TODO the robust kernel is not correctly copied
91 //_robustKernel = e->_robustKernel;
92}
93
94//
95// Rigid 3D constraint between poses, given fixed point offsets
96//
97
98// input two matched points between the frames
99// first point belongs to the first frame, position and normal
100// second point belongs to the second frame, position and normal
101//
102// the measurement variable has type EdgeGICP (see types_icp.h)
103
104bool Edge_V_V_GICP::read(std::istream& is) {
105 // measured point and normal
106 for (int i = 0; i < 3; i++) is >> _measurement.pos0[i];
107 for (int i = 0; i < 3; i++) is >> _measurement.normal0[i];
108
109 // measured point and normal
110 for (int i = 0; i < 3; i++) is >> _measurement.pos1[i];
111 for (int i = 0; i < 3; i++) is >> _measurement.normal1[i];
112
113 // don't need this if we don't use it in error calculation (???)
114 // inverseMeasurement() = -measurement();
115
116 _measurement.makeRot0(); // set up rotation matrices
117
118 // GICP info matrices
119
120 // point-plane only
121 Matrix3 prec;
122 double v = cst(.01);
123 prec << v, 0, 0, 0, v, 0, 0, 0, 1;
124 const Matrix3& R = measurement().R0; // plane of the point in vp0
125 information() = R.transpose() * prec * R;
126
127 // information().setIdentity();
128
129 // setRobustKernel(true);
130 // setHuberWidth(0.01); // units? m?
131
132 return true;
133}
134
135// Jacobian
136// [ -R0'*R1 | R0 * dRdx/ddx * 0p1 ]
137// [ R0'*R1 | R0 * dR'dx/ddx * 0p1 ]
138
139#ifdef GICP_ANALYTIC_JACOBIANS
140
141// jacobian defined as:
142// f(T0,T1) = dR0.inv() * T0.inv() * (T1 * dR1 * p1 + dt1) - dt0
143// df/dx0 = [-I, d[dR0.inv()]/dq0 * T01 * p1]
144// df/dx1 = [R0, T01 * d[dR1]/dq1 * p1]
146 VertexSE3* vp0 = static_cast<VertexSE3*>(_vertices[0]);
147 VertexSE3* vp1 = static_cast<VertexSE3*>(_vertices[1]);
148
149 // topLeftCorner<3,3>() is the rotation matrix
150 Matrix3 R0T = vp0->estimate().matrix().topLeftCorner<3, 3>().transpose();
151 Vector3 p1 = measurement().pos1;
152
153 // this could be more efficient
154 if (!vp0->fixed()) {
155 Isometry3 T01 = vp0->estimate().inverse() * vp1->estimate();
156 Vector3 p1t = T01 * p1;
157 _jacobianOplusXi.block<3, 3>(0, 0) = -Matrix3::Identity();
158 _jacobianOplusXi.block<3, 1>(0, 3) = dRidx * p1t;
159 _jacobianOplusXi.block<3, 1>(0, 4) = dRidy * p1t;
160 _jacobianOplusXi.block<3, 1>(0, 5) = dRidz * p1t;
161 }
162
163 if (!vp1->fixed()) {
164 Matrix3 R1 = vp1->estimate().matrix().topLeftCorner<3, 3>();
165 R0T = R0T * R1;
166 _jacobianOplusXj.block<3, 3>(0, 0) = R0T;
167 _jacobianOplusXj.block<3, 1>(0, 3) = R0T * dRidx.transpose() * p1;
168 _jacobianOplusXj.block<3, 1>(0, 4) = R0T * dRidy.transpose() * p1;
169 _jacobianOplusXj.block<3, 1>(0, 5) = R0T * dRidz.transpose() * p1;
170 }
171}
172#endif
173
174bool Edge_V_V_GICP::write(std::ostream& os) const {
175 // first point
176 for (int i = 0; i < 3; i++) os << measurement().pos0[i] << " ";
177 for (int i = 0; i < 3; i++) os << measurement().normal0[i] << " ";
178
179 // second point
180 for (int i = 0; i < 3; i++) os << measurement().pos1[i] << " ";
181 for (int i = 0; i < 3; i++) os << measurement().normal1[i] << " ";
182
183 return os.good();
184}
185
186//
187// stereo camera functions
188//
189
191
193
194#ifdef SCAM_ANALYTIC_JACOBIANS
199 VertexSCam* vc = static_cast<VertexSCam*>(_vertices[1]);
200
201 VertexPointXYZ* vp = static_cast<VertexPointXYZ*>(_vertices[0]);
202 Vector4 pt, trans;
203 pt.head<3>() = vp->estimate();
204 pt(3) = 1.0;
205 trans.head<3>() = vc->estimate().translation();
206 trans(3) = 1.0;
207
208 // first get the world point in camera coords
209 Eigen::Matrix<double, 3, 1, Eigen::ColMajor> pc = vc->w2n * pt;
210
211 // Jacobians wrt camera parameters
212 // set d(quat-x) values [ pz*dpx/dx - px*dpz/dx ] / pz^2
213 double px = pc(0);
214 double py = pc(1);
215 double pz = pc(2);
216 double ipz2 = 1.0 / (pz * pz);
217 if (isnan(ipz2)) {
218 std::cout << "[SetJac] infinite jac" << std::endl;
219 *(int*)0x0 = 0;
220 }
221
222 double ipz2fx = ipz2 * vc->Kcam(0, 0); // Fx
223 double ipz2fy = ipz2 * vc->Kcam(1, 1); // Fy
224 double b = vc->baseline; // stereo baseline
225
226 Eigen::Matrix<double, 3, 1, Eigen::ColMajor> pwt;
227
228 // check for local vars
229 pwt = (pt - trans)
230 .head<3>(); // transform translations, use differential rotation
231
232 // dx
233 Eigen::Matrix<double, 3, 1, Eigen::ColMajor> dp =
234 vc->dRdx * pwt; // dR'/dq * [pw - t]
235 _jacobianOplusXj(0, 3) = (pz * dp(0) - px * dp(2)) * ipz2fx;
236 _jacobianOplusXj(1, 3) = (pz * dp(1) - py * dp(2)) * ipz2fy;
237 _jacobianOplusXj(2, 3) =
238 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
239 // dy
240 dp = vc->dRdy * pwt; // dR'/dq * [pw - t]
241 _jacobianOplusXj(0, 4) = (pz * dp(0) - px * dp(2)) * ipz2fx;
242 _jacobianOplusXj(1, 4) = (pz * dp(1) - py * dp(2)) * ipz2fy;
243 _jacobianOplusXj(2, 4) =
244 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
245 // dz
246 dp = vc->dRdz * pwt; // dR'/dq * [pw - t]
247 _jacobianOplusXj(0, 5) = (pz * dp(0) - px * dp(2)) * ipz2fx;
248 _jacobianOplusXj(1, 5) = (pz * dp(1) - py * dp(2)) * ipz2fy;
249 _jacobianOplusXj(2, 5) =
250 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
251
252 // set d(t) values [ pz*dpx/dx - px*dpz/dx ] / pz^2
253 dp = -vc->w2n.col(0); // dpc / dx
254 _jacobianOplusXj(0, 0) = (pz * dp(0) - px * dp(2)) * ipz2fx;
255 _jacobianOplusXj(1, 0) = (pz * dp(1) - py * dp(2)) * ipz2fy;
256 _jacobianOplusXj(2, 0) =
257 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
258 dp = -vc->w2n.col(1); // dpc / dy
259 _jacobianOplusXj(0, 1) = (pz * dp(0) - px * dp(2)) * ipz2fx;
260 _jacobianOplusXj(1, 1) = (pz * dp(1) - py * dp(2)) * ipz2fy;
261 _jacobianOplusXj(2, 1) =
262 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
263 dp = -vc->w2n.col(2); // dpc / dz
264 _jacobianOplusXj(0, 2) = (pz * dp(0) - px * dp(2)) * ipz2fx;
265 _jacobianOplusXj(1, 2) = (pz * dp(1) - py * dp(2)) * ipz2fy;
266 _jacobianOplusXj(2, 2) =
267 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
268
269 // Jacobians wrt point parameters
270 // set d(t) values [ pz*dpx/dx - px*dpz/dx ] / pz^2
271 dp = vc->w2n.col(0); // dpc / dx
272 _jacobianOplusXi(0, 0) = (pz * dp(0) - px * dp(2)) * ipz2fx;
273 _jacobianOplusXi(1, 0) = (pz * dp(1) - py * dp(2)) * ipz2fy;
274 _jacobianOplusXi(2, 0) =
275 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
276 dp = vc->w2n.col(1); // dpc / dy
277 _jacobianOplusXi(0, 1) = (pz * dp(0) - px * dp(2)) * ipz2fx;
278 _jacobianOplusXi(1, 1) = (pz * dp(1) - py * dp(2)) * ipz2fy;
279 _jacobianOplusXi(2, 1) =
280 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
281 dp = vc->w2n.col(2); // dpc / dz
282 _jacobianOplusXi(0, 2) = (pz * dp(0) - px * dp(2)) * ipz2fx;
283 _jacobianOplusXi(1, 2) = (pz * dp(1) - py * dp(2)) * ipz2fy;
284 _jacobianOplusXi(2, 2) =
285 (pz * dp(0) - (px - b) * dp(2)) * ipz2fx; // right image px
286}
287#endif
288bool Edge_XYZ_VSC::read(std::istream&) { return false; }
289
290bool Edge_XYZ_VSC::write(std::ostream&) const { return false; }
291
292bool VertexSCam::read(std::istream&) { return false; }
293
294bool VertexSCam::write(std::ostream&) const { return false; }
295
296} // namespace g2o
BaseFixedSizedEdge< D, EdgeGICP, VertexSE3, VertexSE3 >::template JacobianType< D, VertexXj::Dimension > & _jacobianOplusXj
BaseFixedSizedEdge< D, EdgeGICP, VertexSE3, VertexSE3 >::template JacobianType< D, VertexXi::Dimension > & _jacobianOplusXi
EIGEN_STRONG_INLINE const Measurement & measurement() const
accessor functions for the measurement represented by the edge
Definition base_edge.h:119
EIGEN_STRONG_INLINE const InformationType & information() const
information matrix of the constraint
Definition base_edge.h:107
Measurement _measurement
the measurement of the edge
Definition base_edge.h:146
const EstimateType & estimate() const
return the current estimate of the vertex
virtual bool read(std::istream &is)
read the vertex from a stream, i.e., the internal state of the vertex
static Matrix3 dRidy
Definition types_icp.h:218
virtual void linearizeOplus()
static Matrix3 dRidx
Definition types_icp.h:217
static Matrix3 dRidz
Definition types_icp.h:219
virtual bool write(std::ostream &os) const
write the vertex to a stream
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Edge_XYZ_VSC()
virtual bool read(std::istream &is)
read the vertex from a stream, i.e., the internal state of the vertex
virtual bool write(std::ostream &os) const
write the vertex to a stream
VertexContainer _vertices
const Vertex * vertex(size_t i) const
abstract Vertex, your types must derive from that one
bool fixed() const
true => this node is fixed during the optimization
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 Matrix3 dRidy
Definition types_icp.h:331
static Matrix3 dRidx
Definition types_icp.h:330
virtual bool write(std::ostream &os) const
write the vertex to a stream
static double baseline
Definition types_icp.h:246
virtual bool read(std::istream &is)
read the vertex from a stream, i.e., the internal state of the vertex
Eigen::Matrix< double, 3, 4, Eigen::ColMajor > w2n
Definition types_icp.h:250
EIGEN_MAKE_ALIGNED_OPERATOR_NEW VertexSCam()
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_REGISTER_TYPE(name, classname)
Definition factory.h:148
#define G2O_REGISTER_TYPE_GROUP(typeGroupName)
Definition factory.h:156
#define G2O_ATTRIBUTE_CONSTRUCTOR(func)
Definition macros.h:92
Definition jet.h:938
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::Transform< double, 3, Eigen::Isometry, Eigen::ColMajor > Isometry3
Definition eigen_types.h:77
Definition jet.h:876