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 Matrix<double, D, 1> 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 MatrixXd& 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 MatrixXd& 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();
int computeUpperTriangleIndex(int i, int j)