Build a dual graph to compute dual values for equality constrained factors
parent
4ca9d5757f
commit
20fb8ab77d
|
|
@ -391,6 +391,46 @@ namespace gtsam {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
JacobianFactor::shared_ptr GaussianFactorGraph::createDualFactor(Key key,
|
||||||
|
const VariableIndex& variableIndex, const VectorValues& delta) const {
|
||||||
|
typedef GaussianFactor G;
|
||||||
|
typedef JacobianFactor J;
|
||||||
|
std::vector<std::pair<Key, Matrix> > Aterms;
|
||||||
|
Vector b = zero(delta.at(key).size());
|
||||||
|
BOOST_FOREACH(size_t factorIx, variableIndex[key]) {
|
||||||
|
// If it is a constraint, transpose the A matrix to have the jacobian of the dual key
|
||||||
|
J::shared_ptr jacobian(boost::dynamic_pointer_cast<J>(this->at(factorIx)));
|
||||||
|
if (jacobian && jacobian->get_model() && jacobian->get_model()->isConstrained()) {
|
||||||
|
Matrix Ai = jacobian->getA(jacobian->find(key)).transpose();
|
||||||
|
boost::optional<Key> dualKey = jacobian->dualKey();
|
||||||
|
if (!dualKey) {
|
||||||
|
throw std::runtime_error("Fail to create dual factor! " \
|
||||||
|
"Constrained JacobianFactor doesn't have a dual key!");
|
||||||
|
}
|
||||||
|
Aterms.push_back(make_pair(*(dualKey), Ai));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If it is unconstrained, collect the gradient to the b vector
|
||||||
|
G::shared_ptr factor(boost::dynamic_pointer_cast<G>(this->at(factorIx)));
|
||||||
|
b += factor->gradient(key, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boost::make_shared<JacobianFactor>(Aterms, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
GaussianFactorGraph::shared_ptr GaussianFactorGraph::buildDualGraph(
|
||||||
|
const KeySet& constrainedVariables,
|
||||||
|
const VariableIndex& variableIndex,
|
||||||
|
const VectorValues& delta) const {
|
||||||
|
GaussianFactorGraph::shared_ptr dualGraph(new GaussianFactorGraph());
|
||||||
|
BOOST_FOREACH(const Key key, constrainedVariables) {
|
||||||
|
dualGraph->push_back(createDualFactor(key, variableIndex, delta));
|
||||||
|
}
|
||||||
|
return dualGraph;
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
boost::tuple<GaussianFactorGraph, GaussianFactorGraph, GaussianFactorGraph> GaussianFactorGraph::splitConstraints() const {
|
boost::tuple<GaussianFactorGraph, GaussianFactorGraph, GaussianFactorGraph> GaussianFactorGraph::splitConstraints() const {
|
||||||
typedef HessianFactor H;
|
typedef HessianFactor H;
|
||||||
|
|
|
||||||
|
|
@ -328,6 +328,18 @@ namespace gtsam {
|
||||||
*/
|
*/
|
||||||
boost::tuple<GaussianFactorGraph, GaussianFactorGraph, GaussianFactorGraph> splitConstraints() const;
|
boost::tuple<GaussianFactorGraph, GaussianFactorGraph, GaussianFactorGraph> splitConstraints() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a dual graph to estimate dual variables associated with constrained factors
|
||||||
|
*/
|
||||||
|
GaussianFactorGraph::shared_ptr buildDualGraph(
|
||||||
|
const KeySet& constrainedVariables, const VariableIndex& variableIndex,
|
||||||
|
const VectorValues& delta) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a dual factor from a constrained key
|
||||||
|
*/
|
||||||
|
JacobianFactor::shared_ptr createDualFactor(Key key,
|
||||||
|
const VariableIndex& variableIndex, const VectorValues& delta) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Serialization function */
|
/** Serialization function */
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ static SharedDiagonal sigma0_2 = noiseModel::Isotropic::Sigma(2,0.2);
|
||||||
static SharedDiagonal constraintModel = noiseModel::Constrained::All(2);
|
static SharedDiagonal constraintModel = noiseModel::Constrained::All(2);
|
||||||
|
|
||||||
static const Key _l1_=0, _x1_=1, _x2_=2;
|
static const Key _l1_=0, _x1_=1, _x2_=2;
|
||||||
static const Key _x_=0, _y_=1, _z_=2;
|
static const Key _x_=0, _y_=1, _z_=2, _d_=3, _e_=4;
|
||||||
} // \namespace impl
|
} // \namespace impl
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -423,7 +423,7 @@ inline GaussianFactorGraph createSimpleConstraintGraph() {
|
||||||
Matrix Ay1 = eye(2) * -1;
|
Matrix Ay1 = eye(2) * -1;
|
||||||
Vector b2 = (Vector(2) << 0.0, 0.0);
|
Vector b2 = (Vector(2) << 0.0, 0.0);
|
||||||
JacobianFactor::shared_ptr f2(new JacobianFactor(_x_, Ax1, _y_, Ay1, b2,
|
JacobianFactor::shared_ptr f2(new JacobianFactor(_x_, Ax1, _y_, Ay1, b2,
|
||||||
constraintModel));
|
constraintModel, _d_));
|
||||||
|
|
||||||
// construct the graph
|
// construct the graph
|
||||||
GaussianFactorGraph fg;
|
GaussianFactorGraph fg;
|
||||||
|
|
@ -469,7 +469,7 @@ inline GaussianFactorGraph createSingleConstraintGraph() {
|
||||||
Matrix Ay1 = eye(2) * 10;
|
Matrix Ay1 = eye(2) * 10;
|
||||||
Vector b2 = (Vector(2) << 1.0, 2.0);
|
Vector b2 = (Vector(2) << 1.0, 2.0);
|
||||||
JacobianFactor::shared_ptr f2(new JacobianFactor(_x_, Ax1, _y_, Ay1, b2,
|
JacobianFactor::shared_ptr f2(new JacobianFactor(_x_, Ax1, _y_, Ay1, b2,
|
||||||
constraintModel));
|
constraintModel, _d_));
|
||||||
|
|
||||||
// construct the graph
|
// construct the graph
|
||||||
GaussianFactorGraph fg;
|
GaussianFactorGraph fg;
|
||||||
|
|
@ -513,7 +513,7 @@ inline GaussianFactorGraph createMultiConstraintGraph() {
|
||||||
b1(0) = 1.0;
|
b1(0) = 1.0;
|
||||||
b1(1) = 2.0;
|
b1(1) = 2.0;
|
||||||
JacobianFactor::shared_ptr lc1(new JacobianFactor(_x_, A11, _y_, A12, b1,
|
JacobianFactor::shared_ptr lc1(new JacobianFactor(_x_, A11, _y_, A12, b1,
|
||||||
constraintModel));
|
constraintModel, _d_));
|
||||||
|
|
||||||
// constraint 2
|
// constraint 2
|
||||||
Matrix A21(2, 2);
|
Matrix A21(2, 2);
|
||||||
|
|
@ -532,7 +532,7 @@ inline GaussianFactorGraph createMultiConstraintGraph() {
|
||||||
b2(0) = 3.0;
|
b2(0) = 3.0;
|
||||||
b2(1) = 4.0;
|
b2(1) = 4.0;
|
||||||
JacobianFactor::shared_ptr lc2(new JacobianFactor(_x_, A21, _z_, A22, b2,
|
JacobianFactor::shared_ptr lc2(new JacobianFactor(_x_, A21, _z_, A22, b2,
|
||||||
constraintModel));
|
constraintModel, _e_));
|
||||||
|
|
||||||
// construct the graph
|
// construct the graph
|
||||||
GaussianFactorGraph fg;
|
GaussianFactorGraph fg;
|
||||||
|
|
|
||||||
|
|
@ -593,6 +593,55 @@ TEST( GaussianFactorGraph, conditional_sigma_failure) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( GaussianFactorGraph, buildDualGraph1 )
|
||||||
|
{
|
||||||
|
GaussianFactorGraph fgc1 = createSimpleConstraintGraph();
|
||||||
|
KeySet constrainedVariables1 = list_of(0)(1);
|
||||||
|
VariableIndex variableIndex1(fgc1);
|
||||||
|
VectorValues delta1 = createSimpleConstraintValues();
|
||||||
|
GaussianFactorGraph::shared_ptr dualGraph1 = fgc1.buildDualGraph(
|
||||||
|
constrainedVariables1, variableIndex1, delta1);
|
||||||
|
GaussianFactorGraph expectedDualGraph1;
|
||||||
|
expectedDualGraph1.push_back(JacobianFactor(3, eye(2), zero(2)));
|
||||||
|
expectedDualGraph1.push_back(JacobianFactor(3, -eye(2), zero(2)));
|
||||||
|
EXPECT(assert_equal(expectedDualGraph1, *dualGraph1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( GaussianFactorGraph, buildDualGraph2 )
|
||||||
|
{
|
||||||
|
GaussianFactorGraph fgc2 = createSingleConstraintGraph();
|
||||||
|
KeySet constrainedVariables2 = list_of(0)(1);
|
||||||
|
VariableIndex variableIndex2(fgc2);
|
||||||
|
VectorValues delta2 = createSingleConstraintValues();
|
||||||
|
GaussianFactorGraph::shared_ptr dualGraph2 = fgc2.buildDualGraph(
|
||||||
|
constrainedVariables2, variableIndex2, delta2);
|
||||||
|
GaussianFactorGraph expectedDualGraph2;
|
||||||
|
expectedDualGraph2.push_back(JacobianFactor(3, (Matrix(2,2) << 1,2,2,1), zero(2)));
|
||||||
|
expectedDualGraph2.push_back(JacobianFactor(3, 10*eye(2), zero(2)));
|
||||||
|
EXPECT(assert_equal(expectedDualGraph2, *dualGraph2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( GaussianFactorGraph, buildDualGraph3 )
|
||||||
|
{
|
||||||
|
GaussianFactorGraph fgc3 = createMultiConstraintGraph();
|
||||||
|
KeySet constrainedVariables3 = list_of(0)(1)(2);
|
||||||
|
VariableIndex variableIndex3(fgc3);
|
||||||
|
VectorValues delta3 = createMultiConstraintValues();
|
||||||
|
GaussianFactorGraph::shared_ptr dualGraph3 = fgc3.buildDualGraph(
|
||||||
|
constrainedVariables3, variableIndex3, delta3);
|
||||||
|
GaussianFactorGraph expectedDualGraph3;
|
||||||
|
expectedDualGraph3.push_back(
|
||||||
|
JacobianFactor(3, (Matrix(2, 2) << 1, 2, 2, 1), 4,
|
||||||
|
(Matrix(2, 2) << 3, -1, 4, -2), zero(2)));
|
||||||
|
expectedDualGraph3.push_back(JacobianFactor(3, 10*eye(2), zero(2)));
|
||||||
|
expectedDualGraph3.push_back(
|
||||||
|
JacobianFactor(4, (Matrix(2, 2) << 1, 1, 1, 2), zero(2)));
|
||||||
|
EXPECT(assert_equal(expectedDualGraph3, *dualGraph3));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
|
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue