30 int elemsUpToCol = ((j-1) * j) / 2;
31 return elemsUpToCol + i;
35 template <
int D,
typename E>
36 void BaseMultiEdge<D, E>::constructQuadraticForm()
38 if (this->robustKernel()) {
39 double error = this->chi2();
41 this->robustKernel()->robustify(error, rho);
42 Eigen::Matrix<double, D, 1, Eigen::ColMajor> omega_r = - _information * _error;
44 computeQuadraticForm(this->robustInformation(rho), omega_r);
46 computeQuadraticForm(_information, - _information * _error);
51 template <
int D,
typename E>
52 void BaseMultiEdge<D, E>::linearizeOplus(JacobianWorkspace& jacobianWorkspace)
54 for (
size_t i = 0; i < _vertices.size(); ++i) {
55 OptimizableGraph::Vertex* v =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
56 assert(v->dimension() >= 0);
57 new (&_jacobianOplus[i]) JacobianType(jacobianWorkspace.workspaceForVertex(i), D, v->dimension());
62 template <
int D,
typename E>
63 void BaseMultiEdge<D, E>::linearizeOplus()
66 for (
size_t i = 0; i < _vertices.size(); ++i) {
67 OptimizableGraph::Vertex* v =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
68 v->lockQuadraticForm();
72 const double delta = 1e-9;
73 const double scalar = 1.0 / (2*delta);
75 ErrorVector errorBeforeNumeric = _error;
77 for (
size_t i = 0; i < _vertices.size(); ++i) {
79 OptimizableGraph::Vertex* vi =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
84 const int vi_dim = vi->dimension();
87 double* add_vi =
new double[vi_dim];
89 double add_vi[vi_dim];
91 std::fill(add_vi, add_vi + vi_dim, 0.0);
92 assert(_dimension >= 0);
93 assert(_jacobianOplus[i].rows() == _dimension && _jacobianOplus[i].cols() == vi_dim &&
"jacobian cache dimension does not match");
94 _jacobianOplus[i].resize(_dimension, vi_dim);
96 for (
int d = 0; d < vi_dim; ++d) {
111 _jacobianOplus[i].col(d) = scalar * errorBak;
117 _error = errorBeforeNumeric;
120 for (
int i = (
int)(_vertices.size()) - 1; i >= 0; --i) {
121 OptimizableGraph::Vertex* v =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
122 v->unlockQuadraticForm();
128 template <
int D,
typename E>
129 void BaseMultiEdge<D, E>::mapHessianMemory(
double* d,
int i,
int j,
bool rowMajor)
132 assert(idx < (
int)_hessian.size());
133 OptimizableGraph::Vertex* vi =
static_cast<OptimizableGraph::Vertex*
>(HyperGraph::Edge::vertex(i));
134 OptimizableGraph::Vertex* vj =
static_cast<OptimizableGraph::Vertex*
>(HyperGraph::Edge::vertex(j));
135 assert(vi->dimension() >= 0);
136 assert(vj->dimension() >= 0);
137 HessianHelper& h = _hessian[idx];
139 if (h.matrix.data() != d || h.transposed != rowMajor)
140 new (&h.matrix) HessianBlockType(d, vj->dimension(), vi->dimension());
142 if (h.matrix.data() != d || h.transposed != rowMajor)
143 new (&h.matrix) HessianBlockType(d, vi->dimension(), vj->dimension());
145 h.transposed = rowMajor;
148 template <
int D,
typename E>
149 void BaseMultiEdge<D, E>::resize(
size_t size)
151 BaseEdge<D,E>::resize(size);
152 int n = (int)_vertices.size();
153 int maxIdx = (n * (n-1))/2;
155 _hessian.resize(maxIdx);
156 _jacobianOplus.resize(size, JacobianType(0,0,0));
159 template <
int D,
typename E>
160 bool BaseMultiEdge<D, E>::allVerticesFixed()
const 162 for (
size_t i = 0; i < _vertices.size(); ++i) {
163 if (!static_cast<const OptimizableGraph::Vertex*> (_vertices[i])->fixed()) {
170 template <
int D,
typename E>
171 void BaseMultiEdge<D, E>::computeQuadraticForm(
const InformationType& omega,
const ErrorVector& weightedError)
173 for (
size_t i = 0; i < _vertices.size(); ++i) {
174 OptimizableGraph::Vertex* from =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
175 bool istatus = !(from->fixed());
178 const JacobianType& A = _jacobianOplus[i];
180 MatrixXD AtO = A.transpose() * omega;
181 int fromDim = from->dimension();
182 assert(fromDim >= 0);
183 Eigen::Map<MatrixXD> fromMap(from->hessianData(), fromDim, fromDim);
184 Eigen::Map<VectorXD> fromB(from->bData(), fromDim);
188 from->lockQuadraticForm();
190 fromMap.noalias() += AtO * A;
191 fromB.noalias() += A.transpose() * weightedError;
194 for (
size_t j = i+1; j < _vertices.size(); ++j) {
195 OptimizableGraph::Vertex* to =
static_cast<OptimizableGraph::Vertex*
>(_vertices[j]);
197 to->lockQuadraticForm();
199 bool jstatus = !(to->fixed());
201 const JacobianType& B = _jacobianOplus[j];
203 assert(idx < (
int)_hessian.size());
204 HessianHelper& hhelper = _hessian[idx];
205 if (hhelper.transposed) {
206 hhelper.matrix.noalias() += B.transpose() * AtO.transpose();
208 hhelper.matrix.noalias() += AtO * B;
212 to->unlockQuadraticForm();
217 from->unlockQuadraticForm();
227 template <
typename E>
228 void BaseMultiEdge<-1, E>::constructQuadraticForm()
230 if (this->robustKernel()) {
231 double error = this->chi2();
233 this->robustKernel()->robustify(error, rho);
234 Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::ColMajor> omega_r = - _information * _error;
236 computeQuadraticForm(this->robustInformation(rho), omega_r);
238 computeQuadraticForm(_information, - _information * _error);
243 template <
typename E>
244 void BaseMultiEdge<-1, E>::linearizeOplus(JacobianWorkspace& jacobianWorkspace)
246 for (
size_t i = 0; i < _vertices.size(); ++i) {
247 OptimizableGraph::Vertex* v =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
248 assert(v->dimension() >= 0);
249 new (&_jacobianOplus[i]) JacobianType(jacobianWorkspace.workspaceForVertex(i), _dimension, v->dimension());
254 template <
typename E>
255 void BaseMultiEdge<-1, E>::linearizeOplus()
258 for (
size_t i = 0; i < _vertices.size(); ++i) {
259 OptimizableGraph::Vertex* v =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
260 v->lockQuadraticForm();
264 const double delta = 1e-9;
265 const double scalar = 1.0 / (2*delta);
266 ErrorVector errorBak;
267 ErrorVector errorBeforeNumeric = _error;
269 for (
size_t i = 0; i < _vertices.size(); ++i) {
271 OptimizableGraph::Vertex* vi =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
276 const int vi_dim = vi->dimension();
279 double* add_vi =
new double[vi_dim];
281 double add_vi[vi_dim];
283 std::fill(add_vi, add_vi + vi_dim, 0.0);
284 assert(_dimension >= 0);
285 assert(_jacobianOplus[i].rows() == _dimension && _jacobianOplus[i].cols() == vi_dim &&
"jacobian cache dimension does not match");
286 _jacobianOplus[i].resize(_dimension, vi_dim);
288 for (
int d = 0; d < vi_dim; ++d) {
303 _jacobianOplus[i].col(d) = scalar * errorBak;
309 _error = errorBeforeNumeric;
312 for (
int i = (
int)(_vertices.size()) - 1; i >= 0; --i) {
313 OptimizableGraph::Vertex* v =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
314 v->unlockQuadraticForm();
320 template <
typename E>
321 void BaseMultiEdge<-1, E>::mapHessianMemory(
double* d,
int i,
int j,
bool rowMajor)
324 assert(idx < (
int)_hessian.size());
325 OptimizableGraph::Vertex* vi =
static_cast<OptimizableGraph::Vertex*
>(HyperGraph::Edge::vertex(i));
326 OptimizableGraph::Vertex* vj =
static_cast<OptimizableGraph::Vertex*
>(HyperGraph::Edge::vertex(j));
327 assert(vi->dimension() >= 0);
328 assert(vj->dimension() >= 0);
329 HessianHelper& h = _hessian[idx];
331 if (h.matrix.data() != d || h.transposed != rowMajor)
332 new (&h.matrix) HessianBlockType(d, vj->dimension(), vi->dimension());
334 if (h.matrix.data() != d || h.transposed != rowMajor)
335 new (&h.matrix) HessianBlockType(d, vi->dimension(), vj->dimension());
337 h.transposed = rowMajor;
340 template <
typename E>
341 void BaseMultiEdge<-1, E>::resize(
size_t size)
343 BaseEdge<-1,E>::resize(size);
344 int n = (int)_vertices.size();
345 int maxIdx = (n * (n-1))/2;
347 _hessian.resize(maxIdx);
348 _jacobianOplus.resize(size, JacobianType(0,0,0));
351 template <
typename E>
352 bool BaseMultiEdge<-1, E>::allVerticesFixed()
const 354 for (
size_t i = 0; i < _vertices.size(); ++i) {
355 if (!static_cast<const OptimizableGraph::Vertex*> (_vertices[i])->fixed()) {
362 template <
typename E>
363 void BaseMultiEdge<-1, E>::computeQuadraticForm(
const InformationType& omega,
const ErrorVector& weightedError)
365 for (
size_t i = 0; i < _vertices.size(); ++i) {
366 OptimizableGraph::Vertex* from =
static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
367 bool istatus = !(from->fixed());
370 const JacobianType& A = _jacobianOplus[i];
372 MatrixXD AtO = A.transpose() * omega;
373 int fromDim = from->dimension();
374 assert(fromDim >= 0);
375 Eigen::Map<MatrixXD> fromMap(from->hessianData(), fromDim, fromDim);
376 Eigen::Map<VectorXD> fromB(from->bData(), fromDim);
380 from->lockQuadraticForm();
382 fromMap.noalias() += AtO * A;
383 fromB.noalias() += A.transpose() * weightedError;
386 for (
size_t j = i+1; j < _vertices.size(); ++j) {
387 OptimizableGraph::Vertex* to =
static_cast<OptimizableGraph::Vertex*
>(_vertices[j]);
389 to->lockQuadraticForm();
391 bool jstatus = !(to->fixed());
393 const JacobianType& B = _jacobianOplus[j];
395 assert(idx < (
int)_hessian.size());
396 HessianHelper& hhelper = _hessian[idx];
397 if (hhelper.transposed) {
398 hhelper.matrix.noalias() += B.transpose() * AtO.transpose();
400 hhelper.matrix.noalias() += AtO * B;
404 to->unlockQuadraticForm();
409 from->unlockQuadraticForm();
int computeUpperTriangleIndex(int i, int j)
Eigen::Matrix< double, 3, 1, Eigen::ColMajor > Vector3D
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > MatrixXD