31 template <HyperGraph2::EdgeType type>
33 int num_custom_jacobians,
bool edge_based,
const double* multipliers)
35 if (edges.empty() || vertices.empty())
return;
37 constexpr
const double delta = 1e-9;
38 constexpr
const double neg2delta = -2 * delta;
39 constexpr
const double scalar = 1.0 / (2 * delta);
42 if (num_custom_jacobians > 0 || edge_based)
46 if (edge->providesJacobian() || edge_based)
48 for (
int i = 0; i < edge->getNumVertices(); ++i)
50 if (edge->getVertexRaw(i)->getDimensionUnfixed() == 0)
continue;
53 if (!_retain_lsq_form && edge->isLeastSquaresForm())
55 Eigen::MatrixXd jacobf(edge->getDimension(), edge->getVertexRaw(i)->getDimensionUnfixed());
58 edge->computeJacobian(i, jacobf,
nullptr);
59 edge->computeValues();
63 jacobian.block(edge->getEdgeIdx(), edge->getVertexRaw(i)->getVertexIdx(), 1, edge->getVertexRaw(i)->getDimensionUnfixed())
64 .noalias() = 2.0 * multipliers[edge->getEdgeIdx()] * values.transpose() * jacobf;
68 jacobian.block(edge->getEdgeIdx(), edge->getVertexRaw(i)->getVertexIdx(), 1, edge->getVertexRaw(i)->getDimensionUnfixed())
69 .noalias() = 2.0 * values.transpose() * jacobf;
75 edge->computeJacobian(i, jacobian.block(edge->getEdgeIdx(), edge->getVertexRaw(i)->getVertexIdx(), edge->getDimension(),
76 edge->getVertexRaw(i)->getDimensionUnfixed()),
77 multipliers + edge->getEdgeIdx());
79 edge->computeJacobian(i, jacobian.block(edge->getEdgeIdx(), edge->getVertexRaw(i)->getVertexIdx(), edge->getDimension(),
80 edge->getVertexRaw(i)->getDimensionUnfixed()),
86 if (num_custom_jacobians == edges.size() || edge_based)
return;
91 for (VertexInterface* vertex : vertices)
93 if (vertex->getDimensionUnfixed() == 0)
continue;
95 int num_connected_edges;
98 num_connected_edges = (
int)vertex->getConnectedObjectiveEdgesRef().size();
99 if (vertex->getNumObjectiveEdgesWithCustomJacobian() == num_connected_edges)
105 else static_if(type == EdgeType::Equality)
107 num_connected_edges = (
int)vertex->getConnectedEqualityEdgesRef().size();
108 if (vertex->getNumEqualityEdgesWithCustomJacobian() == num_connected_edges)
116 num_connected_edges = (
int)vertex->getConnectedInequalityEdgesRef().size();
117 if (vertex->getNumInequalityEdgesWithCustomJacobian() == num_connected_edges)
124 std::vector<Eigen::VectorXd> values2(num_connected_edges);
126 for (
int i = 0; i < vertex->getDimension(); ++i)
128 if (vertex->isFixedComponent(i))
continue;
130 std::set<EdgeInterface*>* connected_edges;
131 static_if(type == EdgeType::Objective) connected_edges = &vertex->getConnectedObjectiveEdgesRef();
132 else static_if(type == EdgeType::Equality) connected_edges = &vertex->getConnectedEqualityEdgesRef();
133 else connected_edges = &vertex->getConnectedInequalityEdgesRef();
135 vertex->plus(i, delta);
138 for (EdgeInterface* edge : *connected_edges)
140 if (!edge->providesJacobian())
142 edge->computeValues();
147 vertex->plus(i, neg2delta);
149 for (EdgeInterface* edge : *connected_edges)
151 if (!edge->providesJacobian())
153 edge->computeValues();
156 if (!_retain_lsq_form && edge->isLeastSquaresForm())
160 jacobian(edge->getEdgeIdx(), col_idx) =
161 2.0 * values.transpose() * scalar * multipliers[edge->getEdgeIdx()] * (values2[edge_idx] - values);
163 jacobian(edge->getEdgeIdx(), col_idx) = 2.0 * values.transpose() * scalar * (values2[edge_idx] - values);
171 jacobian.block(edge->getEdgeIdx(), col_idx, edge->getDimension(), 1).noalias() =
172 scalar * (values2[edge_idx] - values).cwiseProduct(values_multp);
176 jacobian.block(edge->getEdgeIdx(), col_idx, edge->getDimension(), 1).noalias() = scalar * (values2[edge_idx] - values);
182 vertex->plus(i, delta);
std::unique_ptr< EdgeInterface > UPtr
A matrix or vector expression mapping an existing array of data.
A matrix or vector expression mapping an existing expression.