NDEVR
API Documentation
types_six_dof_expmap.h
1#pragma once
2#include "base_vertex.h"
3#include "base_binary_edge.h"
4#include "base_unary_edge.h"
5#include "vertex_se3_expmap.h"
6#include "se3_ops.h"
7#include "se3quat.h"
8#include "types_sba.h"
9#include <Eigen/Geometry>
10
11namespace NDEVR
12{
13 using namespace Eigen;
14
15 typedef Eigen::Matrix<g_type, 6, 6> Matrix6d;
16
17
18
19
24 class EdgeSE3 : public BaseBinaryEdge<6, SE3Quat, VertexSE3Expmap, VertexSE3Expmap>
25 {
26 public:
27 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
28 EdgeSE3()
30 {}
31 void computeError() final override
32 {
34 SE3Quat error_ = C * m_a->estimate() * m_b->estimate().inverse();
35 _error = error_.log();
36 //if (!_error.array().isFinite().all())
37 //throw "error";
38 }
39 };
40
41
43 class EdgeStereoSE3ProjectXYZ : public BaseBinaryEdge<3, Vector3<g_type>, VertexSBAPointXYZ, VertexSE3Expmap> {
44 public:
45 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
46
47 void computeError() final override
48 {
49 _error = _measurement - cam_project(m_b->estimate().map(m_a->estimate()), bf);
50 //if (!_error.array().isFinite().all())
51 //throw "error";
52 }
53
54 bool isDepthPositive()
55 {
56 return (m_b->estimate().map(m_a->estimate()))(2) > 0.0;
57 }
58
59
60
61 Vector3<g_type> cam_project(const Vector3<g_type>& trans_xyz, g_type bf_a) const
62 {
63 const g_type invz = g_type(1.0) / trans_xyz[2];
64 Vector3<g_type> res;
65 res[0] = trans_xyz[0] * invz * fx + cx;
66 res[1] = trans_xyz[1] * invz * fy + cy;
67 res[2] = res[0] - bf_a * invz;
68 return res;
69 }
70
71 EdgeStereoSE3ProjectXYZ()
72 : BaseBinaryEdge<3, Vector3<g_type>, VertexSBAPointXYZ, VertexSE3Expmap>()
73 , fx(0), fy(0), cx(0), cy(0), bf(0)
74 {}
75
76
77 void linearizeOplus() final override
78 {
79 SE3Quat T(m_b->estimate());
80 Vector3<g_type> xyz = m_a->estimate();
81 Vector3<g_type> xyz_trans = T.map(xyz);
82
83 const Matrix3<g_type> R = T.rotation().toRotationMatrix();
84
85 g_type x = xyz_trans[0];
86 g_type y = xyz_trans[1];
87 g_type z = xyz_trans[2];
88 g_type z_2 = z * z;
89
90 _jacobianOplusXi(0, 0) = -fx * R(0, 0) / z + fx * x * R(2, 0) / z_2;
91 _jacobianOplusXi(0, 1) = -fx * R(0, 1) / z + fx * x * R(2, 1) / z_2;
92 _jacobianOplusXi(0, 2) = -fx * R(0, 2) / z + fx * x * R(2, 2) / z_2;
93
94 _jacobianOplusXi(1, 0) = -fy * R(1, 0) / z + fy * y * R(2, 0) / z_2;
95 _jacobianOplusXi(1, 1) = -fy * R(1, 1) / z + fy * y * R(2, 1) / z_2;
96 _jacobianOplusXi(1, 2) = -fy * R(1, 2) / z + fy * y * R(2, 2) / z_2;
97
98 _jacobianOplusXi(2, 0) = _jacobianOplusXi(0, 0) - bf * R(2, 0) / z_2;
99 _jacobianOplusXi(2, 1) = _jacobianOplusXi(0, 1) - bf * R(2, 1) / z_2;
100 _jacobianOplusXi(2, 2) = _jacobianOplusXi(0, 2) - bf * R(2, 2) / z_2;
101
102 _jacobianOplusXj(0, 0) = x * y / z_2 * fx;
103 _jacobianOplusXj(0, 1) = -(1 + (x * x / z_2)) * fx;
104 _jacobianOplusXj(0, 2) = y / z * fx;
105 _jacobianOplusXj(0, 3) = g_type(- 1.) / z * fx;
106 _jacobianOplusXj(0, 4) = 0;
107 _jacobianOplusXj(0, 5) = x / z_2 * fx;
108
109 _jacobianOplusXj(1, 0) = (1 + y * y / z_2) * fy;
110 _jacobianOplusXj(1, 1) = -x * y / z_2 * fy;
111 _jacobianOplusXj(1, 2) = -x / z * fy;
112 _jacobianOplusXj(1, 3) = 0;
113 _jacobianOplusXj(1, 4) = g_type(-1.) / z * fy;
114 _jacobianOplusXj(1, 5) = y / z_2 * fy;
115
116 _jacobianOplusXj(2, 0) = _jacobianOplusXj(0, 0) - bf * y / z_2;
117 _jacobianOplusXj(2, 1) = _jacobianOplusXj(0, 1) + bf * x / z_2;
120 _jacobianOplusXj(2, 4) = 0;
121 _jacobianOplusXj(2, 5) = _jacobianOplusXj(0, 5) - bf / z_2;
122 }
123
124
125 g_type fx, fy, cx, cy, bf;
126 };
127
128 class EdgeStereoSE3ProjectXYZOnlyPose : public BaseUnaryEdge<3, Vector3<g_type>, VertexSE3Expmap> {
129 public:
130 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
131
132 EdgeStereoSE3ProjectXYZOnlyPose() : fx(0), fy(0), cx(0), cy(0), bf(0) {}
133 void computeError() final override
134 {
135 Vector3<g_type> obs(_measurement);
136 _error = obs - cam_project(m_vertex->estimate().map(Xw));
137 //if (!_error.array().isFinite().all())
138 //throw "error";
139 }
140
141 bool isDepthPositive() const
142 {
143 return (m_vertex->estimate().map(Xw))(2) > 0.0;
144 }
145
146
147 Vector2<g_type> project2d(const Vector3<g_type>& v)
148 {
149 Vector2<g_type> res;
150 res(0) = v(0) / v(2);
151 res(1) = v(1) / v(2);
152 return res;
153 }
154
155 Vector3<g_type> unproject2d(const Vector2<g_type>& v)
156 {
157 Vector3<g_type> res;
158 res(0) = v(0);
159 res(1) = v(1);
160 res(2) = 1;
161 return res;
162 }
163
164
165
166
167 //Only Pose
168
169 Vector3<g_type> cam_project(const Vector3<g_type>& trans_xyz) const
170 {
171 const g_type invz = g_type(1.0) / trans_xyz[2];
172 Vector3<g_type> res;
173 res[0] = trans_xyz[0] * invz * fx + cx;
174 res[1] = trans_xyz[1] * invz * fy + cy;
175 res[2] = res[0] - bf * invz;
176 return res;
177 }
178
179 void linearizeOplus() final override
180 {
181 Vector3<g_type> xyz_trans = m_vertex->estimate().map(Xw);
182
183 g_type x = xyz_trans[0];
184 g_type y = xyz_trans[1];
185 //if (abs(xyz_trans[2]) < 1e-12)
186 //throw "sd";
187 g_type invz = g_type(1.0) / xyz_trans[2];
188 g_type invz_2 = invz * invz;
189
190 _jacobianOplusXi(0, 0) = x * y * invz_2 * fx;
191 _jacobianOplusXi(0, 1) = -(1 + (x * x * invz_2)) * fx;
192 _jacobianOplusXi(0, 2) = y * invz * fx;
193 _jacobianOplusXi(0, 3) = -invz * fx;
194 _jacobianOplusXi(0, 4) = 0;
195 _jacobianOplusXi(0, 5) = x * invz_2 * fx;
196
197 _jacobianOplusXi(1, 0) = (1 + y * y * invz_2) * fy;
198 _jacobianOplusXi(1, 1) = -x * y * invz_2 * fy;
199 _jacobianOplusXi(1, 2) = -x * invz * fy;
200 _jacobianOplusXi(1, 3) = 0;
201 _jacobianOplusXi(1, 4) = -invz * fy;
202 _jacobianOplusXi(1, 5) = y * invz_2 * fy;
203
204 _jacobianOplusXi(2, 0) = _jacobianOplusXi(0, 0) - bf * y * invz_2;
205 _jacobianOplusXi(2, 1) = _jacobianOplusXi(0, 1) + bf * x * invz_2;
208 _jacobianOplusXi(2, 4) = 0;
209 _jacobianOplusXi(2, 5) = _jacobianOplusXi(0, 5) - bf * invz_2;
210 }
211 Vector3<g_type> Xw;
212 g_type fx, fy, cx, cy, bf;
213 };
214
215}
Measurement _measurement
Definition base_edge.h:75
const EstimateType & estimate() const
return the current estimate of the vertex
void computeError() final override
Computes the error of the edge and stores it internally.
g_type bf
Camera intrinsics: focal lengths, principal point, and stereo baseline * focal length.
Vector3< g_type > Xw
Known 3D world point.
void linearizeOplus() final override
Linearizes the oplus operator in the vertex, and stores the result in temporary variables _jacobianOp...
void computeError() final override
Computes the error of the edge and stores it internally.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW void computeError() final override
Computes the error of the edge and stores it internally.
void linearizeOplus() final override
Numerically linearizes the oplus operator by finite differences for both vertices.
g_type bf
Camera intrinsics: focal lengths, principal point, and stereo baseline * focal length.
SE(3) rigid body transformation represented by a unit quaternion and translation vector.
Definition se3quat.h:42
const Quaternion< g_type > & rotation() const
Returns a const reference to the rotation quaternion.
Definition se3quat.h:116
Vector6d log() const
Computes the logarithmic map (SE3 -> 6D tangent vector).
Definition se3quat.h:209
Vector3< g_type > map(const Vector3< g_type > &xyz) const
Transforms a 3D point: R*xyz + t.
Definition se3quat.h:263
The primary namespace for the NDEVR SDK.
Eigen::Matrix< g_type, 6, 6 > Matrix6d
6x6 matrix type for SE3 operations.