31 int elemsUpToCol = ((j - 1) * j) / 2;
32 return elemsUpToCol + i;
36template <
int D,
typename E>
37void BaseVariableSizedEdge<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 =
43 -_information * _error;
45 computeQuadraticForm(this->robustInformation(rho), omega_r);
47 computeQuadraticForm(_information, -_information * _error);
51template <
int D,
typename E>
52void BaseVariableSizedEdge<D, E>::linearizeOplus(
53 JacobianWorkspace& jacobianWorkspace) {
54 for (
size_t i = 0; i < _vertices.size(); ++i) {
55 OptimizableGraph::Vertex* v =
56 static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
57 assert(v->dimension() >= 0);
58 new (&_jacobianOplus[i])
59 JacobianType(jacobianWorkspace.workspaceForVertex(i),
60 D < 0 ? _dimension : D, v->dimension());
65template <
int D,
typename E>
66void BaseVariableSizedEdge<D, E>::linearizeOplus() {
67 const double delta =
cst(1e-9);
68 const double scalar = 1 / (2 * delta);
70 ErrorVector errorBeforeNumeric = _error;
72 for (
size_t i = 0; i < _vertices.size(); ++i) {
74 OptimizableGraph::Vertex* vi =
75 static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
81 internal::QuadraticFormLock lck(*vi);
82 const int vi_dim = vi->dimension();
85 assert(_dimension >= 0);
86 assert(_jacobianOplus[i].rows() == _dimension &&
87 _jacobianOplus[i].cols() == vi_dim &&
88 "jacobian cache dimension does not match");
89 _jacobianOplus[i].resize(_dimension, vi_dim);
91 ceres::internal::FixedArray<double> add_vi(vi_dim);
93 for (
int d = 0; d < vi_dim; ++d) {
96 vi->oplus(add_vi.data());
102 vi->oplus(add_vi.data());
108 _jacobianOplus[i].col(d) = scalar * errorBak;
110 _error = errorBeforeNumeric;
114template <
int D,
typename E>
115void BaseVariableSizedEdge<D, E>::mapHessianMemory(
double* d,
int i,
int j,
118 assert(idx < (
int)_hessian.size());
119 OptimizableGraph::Vertex* vi =
120 static_cast<OptimizableGraph::Vertex*
>(HyperGraph::Edge::vertex(i));
121 OptimizableGraph::Vertex* vj =
122 static_cast<OptimizableGraph::Vertex*
>(HyperGraph::Edge::vertex(j));
123 assert(vi->dimension() >= 0);
124 assert(vj->dimension() >= 0);
125 HessianHelper& h = _hessian[idx];
127 if (h.matrix.data() != d || h.transposed != rowMajor)
128 new (&h.matrix) HessianBlockType(d, vj->dimension(), vi->dimension());
130 if (h.matrix.data() != d || h.transposed != rowMajor)
131 new (&h.matrix) HessianBlockType(d, vi->dimension(), vj->dimension());
133 h.transposed = rowMajor;
136template <
int D,
typename E>
137void BaseVariableSizedEdge<D, E>::resize(
size_t size) {
138 BaseEdge<D, E>::resize(size);
139 int n = (int)_vertices.size();
140 int maxIdx = (n * (n - 1)) / 2;
142 _hessian.resize(maxIdx);
143 _jacobianOplus.resize(size, JacobianType(0, 0, 0));
146template <
int D,
typename E>
147bool BaseVariableSizedEdge<D, E>::allVerticesFixed()
const {
148 for (
size_t i = 0; i < _vertices.size(); ++i) {
149 if (!
static_cast<const OptimizableGraph::Vertex*
>(_vertices[i])->fixed()) {
156template <
int D,
typename E>
157void BaseVariableSizedEdge<D, E>::computeQuadraticForm(
158 const InformationType& omega,
const ErrorVector& weightedError) {
159 for (
size_t i = 0; i < _vertices.size(); ++i) {
160 OptimizableGraph::Vertex* from =
161 static_cast<OptimizableGraph::Vertex*
>(_vertices[i]);
162 bool istatus = !(from->fixed());
165 const JacobianType& A = _jacobianOplus[i];
167 MatrixX AtO = A.transpose() * omega;
168 int fromDim = from->dimension();
169 assert(fromDim >= 0);
170 Eigen::Map<MatrixX> fromMap(from->hessianData(), fromDim, fromDim);
171 Eigen::Map<VectorX> fromB(from->bData(), fromDim);
175 internal::QuadraticFormLock lck(*from);
176 fromMap.noalias() += AtO * A;
177 fromB.noalias() += A.transpose() * weightedError;
181 for (
size_t j = i + 1; j < _vertices.size(); ++j) {
182 OptimizableGraph::Vertex* to =
183 static_cast<OptimizableGraph::Vertex*
>(_vertices[j]);
185 bool jstatus = !(to->fixed());
187 internal::QuadraticFormLock lck(*to);
188 const JacobianType& B = _jacobianOplus[j];
190 assert(idx < (
int)_hessian.size());
191 HessianHelper& hhelper = _hessian[idx];
194 hhelper.matrix.noalias() += B.transpose() * AtO.transpose();
196 hhelper.matrix.noalias() += AtO * B;
MatrixN< Eigen::Dynamic > MatrixX
constexpr double cst(long double v)
int computeUpperTriangleIndex(int i, int j)