Returning GaussianFactor instead of JacobianFactor from NonlinearFactor::linearize and NonlinearFactorGraph::linearize, so that HessianFactors may be returned as well.

release/4.3a0
Richard Roberts 2011-04-12 21:18:10 +00:00
parent 6d5dee0860
commit 5057138ef1
14 changed files with 52 additions and 47 deletions

View File

@ -130,13 +130,13 @@ namespace gtsam {
} }
// Linearize is over-written, because base linearization tries to whiten // Linearize is over-written, because base linearization tries to whiten
virtual JacobianFactor::shared_ptr linearize(const VALUES& x, const Ordering& ordering) const { virtual GaussianFactor::shared_ptr linearize(const VALUES& x, const Ordering& ordering) const {
const T& xj = x[this->key_]; const T& xj = x[this->key_];
Matrix A; Matrix A;
Vector b = evaluateError(xj, A); Vector b = evaluateError(xj, A);
// TODO pass unwhitened + noise model to Gaussian factor // TODO pass unwhitened + noise model to Gaussian factor
SharedDiagonal model = noiseModel::Constrained::All(b.size()); SharedDiagonal model = noiseModel::Constrained::All(b.size());
return JacobianFactor::shared_ptr(new JacobianFactor(ordering[this->key_], A, b, model)); return GaussianFactor::shared_ptr(new JacobianFactor(ordering[this->key_], A, b, model));
} }
private: private:

View File

@ -145,7 +145,7 @@ namespace gtsam {
} }
/** linearize to a GaussianFactor */ /** linearize to a GaussianFactor */
virtual boost::shared_ptr<JacobianFactor> virtual boost::shared_ptr<GaussianFactor>
linearize(const VALUES& c, const Ordering& ordering) const = 0; linearize(const VALUES& c, const Ordering& ordering) const = 0;
/** /**
@ -237,7 +237,7 @@ namespace gtsam {
* Ax-b \approx h(x0+dx)-z = h(x0) + A*dx - z * Ax-b \approx h(x0+dx)-z = h(x0) + A*dx - z
* Hence b = z - h(x0) = - error_vector(x) * Hence b = z - h(x0) = - error_vector(x)
*/ */
virtual boost::shared_ptr<JacobianFactor> linearize(const VALUES& x, const Ordering& ordering) const { virtual boost::shared_ptr<GaussianFactor> linearize(const VALUES& x, const Ordering& ordering) const {
const X& xj = x[key_]; const X& xj = x[key_];
Matrix A; Matrix A;
Vector b = - evaluateError(xj, A); Vector b = - evaluateError(xj, A);
@ -246,10 +246,10 @@ namespace gtsam {
SharedDiagonal constrained = SharedDiagonal constrained =
boost::shared_dynamic_cast<noiseModel::Constrained>(this->noiseModel_); boost::shared_dynamic_cast<noiseModel::Constrained>(this->noiseModel_);
if (constrained.get() != NULL) if (constrained.get() != NULL)
return JacobianFactor::shared_ptr(new JacobianFactor(var, A, b, constrained)); return GaussianFactor::shared_ptr(new JacobianFactor(var, A, b, constrained));
this->noiseModel_->WhitenInPlace(A); this->noiseModel_->WhitenInPlace(A);
this->noiseModel_->whitenInPlace(b); this->noiseModel_->whitenInPlace(b);
return JacobianFactor::shared_ptr(new JacobianFactor(var, A, b, return GaussianFactor::shared_ptr(new JacobianFactor(var, A, b,
noiseModel::Unit::Create(b.size()))); noiseModel::Unit::Create(b.size())));
} }
@ -348,7 +348,7 @@ namespace gtsam {
* Ax-b \approx h(x1+dx1,x2+dx2)-z = h(x1,x2) + A2*dx1 + A2*dx2 - z * Ax-b \approx h(x1+dx1,x2+dx2)-z = h(x1,x2) + A2*dx1 + A2*dx2 - z
* Hence b = z - h(x1,x2) = - error_vector(x) * Hence b = z - h(x1,x2) = - error_vector(x)
*/ */
boost::shared_ptr<JacobianFactor> linearize(const VALUES& c, const Ordering& ordering) const { boost::shared_ptr<GaussianFactor> linearize(const VALUES& c, const Ordering& ordering) const {
const X1& x1 = c[key1_]; const X1& x1 = c[key1_];
const X2& x2 = c[key2_]; const X2& x2 = c[key2_];
Matrix A1, A2; Matrix A1, A2;
@ -365,10 +365,10 @@ namespace gtsam {
this->noiseModel_->WhitenInPlace(A2); this->noiseModel_->WhitenInPlace(A2);
this->noiseModel_->whitenInPlace(b); this->noiseModel_->whitenInPlace(b);
if(var1 < var2) if(var1 < var2)
return JacobianFactor::shared_ptr(new JacobianFactor(var1, A1, var2, return GaussianFactor::shared_ptr(new JacobianFactor(var1, A1, var2,
A2, b, noiseModel::Unit::Create(b.size()))); A2, b, noiseModel::Unit::Create(b.size())));
else else
return JacobianFactor::shared_ptr(new JacobianFactor(var2, A2, var1, return GaussianFactor::shared_ptr(new JacobianFactor(var2, A2, var1,
A1, b, noiseModel::Unit::Create(b.size()))); A1, b, noiseModel::Unit::Create(b.size())));
} }
@ -492,7 +492,7 @@ namespace gtsam {
* Ax-b \approx h(x1+dx1,x2+dx2,x3+dx3)-z = h(x1,x2,x3) + A2*dx1 + A2*dx2 + A3*dx3 - z * Ax-b \approx h(x1+dx1,x2+dx2,x3+dx3)-z = h(x1,x2,x3) + A2*dx1 + A2*dx2 + A3*dx3 - z
* Hence b = z - h(x1,x2,x3) = - error_vector(x) * Hence b = z - h(x1,x2,x3) = - error_vector(x)
*/ */
boost::shared_ptr<JacobianFactor> linearize(const VALUES& c, const Ordering& ordering) const { boost::shared_ptr<GaussianFactor> linearize(const VALUES& c, const Ordering& ordering) const {
const X1& x1 = c[key1_]; const X1& x1 = c[key1_];
const X2& x2 = c[key2_]; const X2& x2 = c[key2_];
const X3& x3 = c[key3_]; const X3& x3 = c[key3_];
@ -503,7 +503,7 @@ namespace gtsam {
SharedDiagonal constrained = SharedDiagonal constrained =
boost::shared_dynamic_cast<noiseModel::Constrained>(this->noiseModel_); boost::shared_dynamic_cast<noiseModel::Constrained>(this->noiseModel_);
if (constrained.get() != NULL) { if (constrained.get() != NULL) {
return JacobianFactor::shared_ptr( return GaussianFactor::shared_ptr(
new JacobianFactor(var1, A1, var2, A2, var3, A3, b, constrained)); new JacobianFactor(var1, A1, var2, A2, var3, A3, b, constrained));
} }
this->noiseModel_->WhitenInPlace(A1); this->noiseModel_->WhitenInPlace(A1);
@ -511,26 +511,26 @@ namespace gtsam {
this->noiseModel_->WhitenInPlace(A3); this->noiseModel_->WhitenInPlace(A3);
this->noiseModel_->whitenInPlace(b); this->noiseModel_->whitenInPlace(b);
if(var1 < var2 && var2 < var3) if(var1 < var2 && var2 < var3)
return JacobianFactor::shared_ptr( return GaussianFactor::shared_ptr(
new JacobianFactor(var1, A1, var2, A2, var3, A3, b, noiseModel::Unit::Create(b.size()))); new JacobianFactor(var1, A1, var2, A2, var3, A3, b, noiseModel::Unit::Create(b.size())));
else if(var2 < var1 && var1 < var3) else if(var2 < var1 && var1 < var3)
return JacobianFactor::shared_ptr( return GaussianFactor::shared_ptr(
new JacobianFactor(var2, A2, var1, A1, var3, A3, b, noiseModel::Unit::Create(b.size()))); new JacobianFactor(var2, A2, var1, A1, var3, A3, b, noiseModel::Unit::Create(b.size())));
else if(var1 < var3 && var3 < var2) else if(var1 < var3 && var3 < var2)
return JacobianFactor::shared_ptr( return GaussianFactor::shared_ptr(
new JacobianFactor(var1, A1, var3, A3, var2, A2, b, noiseModel::Unit::Create(b.size()))); new JacobianFactor(var1, A1, var3, A3, var2, A2, b, noiseModel::Unit::Create(b.size())));
else if(var2 < var3 && var3 < var1) else if(var2 < var3 && var3 < var1)
return JacobianFactor::shared_ptr( return GaussianFactor::shared_ptr(
new JacobianFactor(var2, A2, var3, A3, var1, A1, b, noiseModel::Unit::Create(b.size()))); new JacobianFactor(var2, A2, var3, A3, var1, A1, b, noiseModel::Unit::Create(b.size())));
else if(var3 < var1 && var1 < var2) else if(var3 < var1 && var1 < var2)
return JacobianFactor::shared_ptr( return GaussianFactor::shared_ptr(
new JacobianFactor(var3, A3, var1, A1, var2, A2, b, noiseModel::Unit::Create(b.size()))); new JacobianFactor(var3, A3, var1, A1, var2, A2, b, noiseModel::Unit::Create(b.size())));
else if(var3 < var2 && var2 < var1) else if(var3 < var2 && var2 < var1)
return JacobianFactor::shared_ptr( return GaussianFactor::shared_ptr(
new JacobianFactor(var3, A3, var2, A2, var1, A1, b, noiseModel::Unit::Create(b.size()))); new JacobianFactor(var3, A3, var2, A2, var1, A1, b, noiseModel::Unit::Create(b.size())));
else { else {
assert(false); assert(false);
return JacobianFactor::shared_ptr(); return GaussianFactor::shared_ptr();
} }
} }

View File

@ -139,21 +139,20 @@ namespace gtsam {
/* ************************************************************************* */ /* ************************************************************************* */
template<class VALUES> template<class VALUES>
typename FactorGraph<JacobianFactor>::shared_ptr NonlinearFactorGraph<VALUES>::linearize( typename FactorGraph<GaussianFactor>::shared_ptr NonlinearFactorGraph<VALUES>::linearize(
const VALUES& config, const Ordering& ordering) const { const VALUES& config, const Ordering& ordering) const {
// create an empty linear FG // create an empty linear FG
typename FactorGraph<JacobianFactor>::shared_ptr linearFG(new FactorGraph< typename FactorGraph<GaussianFactor>::shared_ptr linearFG(new FactorGraph<GaussianFactor>);
JacobianFactor> );
linearFG->reserve(this->size()); linearFG->reserve(this->size());
// linearize all factors // linearize all factors
BOOST_FOREACH(const sharedFactor& factor, this->factors_) { BOOST_FOREACH(const sharedFactor& factor, this->factors_) {
if(factor) { if(factor) {
JacobianFactor::shared_ptr lf = factor->linearize(config, ordering); GaussianFactor::shared_ptr lf = factor->linearize(config, ordering);
if (lf) linearFG->push_back(lf); if (lf) linearFG->push_back(lf);
} else } else
linearFG->push_back(FactorGraph<JacobianFactor>::sharedFactor()); linearFG->push_back(GaussianFactor::shared_ptr());
} }
return linearFG; return linearFG;

View File

@ -89,7 +89,7 @@ namespace gtsam {
/** /**
* linearize a nonlinear factor graph * linearize a nonlinear factor graph
*/ */
boost::shared_ptr<FactorGraph<JacobianFactor> > boost::shared_ptr<FactorGraph<GaussianFactor> >
linearize(const VALUES& config, const Ordering& ordering) const; linearize(const VALUES& config, const Ordering& ordering) const;
private: private:

View File

@ -273,7 +273,7 @@ namespace example {
} }
/* ************************************************************************* */ /* ************************************************************************* */
pair<FactorGraph<JacobianFactor>, Ordering> createSmoother(int T, boost::optional<Ordering> ordering) { pair<FactorGraph<GaussianFactor>, Ordering> createSmoother(int T, boost::optional<Ordering> ordering) {
Graph nlfg; Graph nlfg;
Values poses; Values poses;
boost::tie(nlfg, poses) = createNonlinearSmoother(T); boost::tie(nlfg, poses) = createNonlinearSmoother(T);
@ -431,7 +431,7 @@ namespace example {
} }
/* ************************************************************************* */ /* ************************************************************************* */
boost::tuple<FactorGraph<JacobianFactor>, Ordering, VectorValues> planarGraph(size_t N) { boost::tuple<FactorGraph<GaussianFactor>, Ordering, VectorValues> planarGraph(size_t N) {
// create empty graph // create empty graph
NonlinearFactorGraph<Values> nlfg; NonlinearFactorGraph<Values> nlfg;

View File

@ -93,7 +93,7 @@ namespace gtsam {
* Create a Kalman smoother by linearizing a non-linear factor graph * Create a Kalman smoother by linearizing a non-linear factor graph
* @param T number of time-steps * @param T number of time-steps
*/ */
std::pair<FactorGraph<JacobianFactor>, Ordering> createSmoother(int T, boost::optional<Ordering> ordering = boost::none); std::pair<FactorGraph<GaussianFactor>, Ordering> createSmoother(int T, boost::optional<Ordering> ordering = boost::none);
/* ******************************************************* */ /* ******************************************************* */
// Linear Constrained Examples // Linear Constrained Examples
@ -133,7 +133,7 @@ namespace gtsam {
* -x11-x21-x31 * -x11-x21-x31
* with x11 clamped at (1,1), and others related by 2D odometry. * with x11 clamped at (1,1), and others related by 2D odometry.
*/ */
boost::tuple<FactorGraph<JacobianFactor>, Ordering, VectorValues> planarGraph(size_t N); boost::tuple<FactorGraph<GaussianFactor>, Ordering, VectorValues> planarGraph(size_t N);
/* /*
* Create canonical ordering for planar graph that also works for tree * Create canonical ordering for planar graph that also works for tree

View File

@ -52,7 +52,8 @@ TEST( Pose2Factor, error )
// Actual linearization // Actual linearization
Ordering ordering(*x0.orderingArbitrary()); Ordering ordering(*x0.orderingArbitrary());
boost::shared_ptr<JacobianFactor> linear = factor.linearize(x0, ordering); boost::shared_ptr<JacobianFactor> linear =
boost::dynamic_pointer_cast<JacobianFactor>(factor.linearize(x0, ordering));
// Check error at x0, i.e. delta = zero ! // Check error at x0, i.e. delta = zero !
VectorValues delta(x0.dims(ordering)); VectorValues delta(x0.dims(ordering));
@ -88,7 +89,8 @@ TEST( Pose2Factor, rhs )
// Actual linearization // Actual linearization
Ordering ordering(*x0.orderingArbitrary()); Ordering ordering(*x0.orderingArbitrary());
boost::shared_ptr<JacobianFactor> linear = factor.linearize(x0, ordering); boost::shared_ptr<JacobianFactor> linear =
boost::dynamic_pointer_cast<JacobianFactor>(factor.linearize(x0, ordering));
// Check RHS // Check RHS
Pose2 hx0 = p1.between(p2); Pose2 hx0 = p1.between(p2);
@ -134,7 +136,8 @@ TEST( Pose2Factor, linearize )
JacobianFactor expected(ordering["x1"], expectedH1, ordering["x2"], expectedH2, expected_b, probModel1); JacobianFactor expected(ordering["x1"], expectedH1, ordering["x2"], expectedH2, expected_b, probModel1);
// Actual linearization // Actual linearization
boost::shared_ptr<JacobianFactor> actual = factor.linearize(x0, ordering); boost::shared_ptr<JacobianFactor> actual =
boost::dynamic_pointer_cast<JacobianFactor>(factor.linearize(x0, ordering));
CHECK(assert_equal(expected,*actual)); CHECK(assert_equal(expected,*actual));
// Numerical do not work out because BetweenFactor is approximate ? // Numerical do not work out because BetweenFactor is approximate ?

View File

@ -44,7 +44,8 @@ TEST( Pose2Prior, error )
// Actual linearization // Actual linearization
Ordering ordering(*x0.orderingArbitrary()); Ordering ordering(*x0.orderingArbitrary());
boost::shared_ptr<JacobianFactor> linear = factor.linearize(x0, ordering); boost::shared_ptr<JacobianFactor> linear =
boost::dynamic_pointer_cast<JacobianFactor>(factor.linearize(x0, ordering));
// Check error at x0, i.e. delta = zero ! // Check error at x0, i.e. delta = zero !
VectorValues delta(x0.dims(ordering)); VectorValues delta(x0.dims(ordering));
@ -86,7 +87,8 @@ TEST( Pose2Prior, linearize )
// Actual linearization // Actual linearization
Ordering ordering(*x0.orderingArbitrary()); Ordering ordering(*x0.orderingArbitrary());
boost::shared_ptr<JacobianFactor> actual = factor.linearize(x0, ordering); boost::shared_ptr<JacobianFactor> actual =
boost::dynamic_pointer_cast<JacobianFactor>(factor.linearize(x0, ordering));
// Test with numerical derivative // Test with numerical derivative
Matrix numericalH = numericalDerivative11(h, prior); Matrix numericalH = numericalDerivative11(h, prior);

View File

@ -74,11 +74,11 @@ TEST( Pose2Graph, linearization )
config.insert(2,p2); config.insert(2,p2);
// Linearize // Linearize
Ordering ordering(*config.orderingArbitrary()); Ordering ordering(*config.orderingArbitrary());
boost::shared_ptr<FactorGraph<JacobianFactor> > lfg_linearized = graph.linearize(config, ordering); boost::shared_ptr<FactorGraph<GaussianFactor> > lfg_linearized = graph.linearize(config, ordering);
//lfg_linearized->print("lfg_actual"); //lfg_linearized->print("lfg_actual");
// the expected linear factor // the expected linear factor
FactorGraph<JacobianFactor> lfg_expected; FactorGraph<GaussianFactor> lfg_expected;
Matrix A1 = Matrix_(3,3, Matrix A1 = Matrix_(3,3,
0.0,-2.0, -4.2, 0.0,-2.0, -4.2,
2.0, 0.0, -4.2, 2.0, 0.0, -4.2,

View File

@ -67,15 +67,16 @@ TEST( ProjectionFactor, error )
Vector b = Vector_(2,3.,0.); Vector b = Vector_(2,3.,0.);
SharedDiagonal probModel1 = noiseModel::Unit::Create(2); SharedDiagonal probModel1 = noiseModel::Unit::Create(2);
JacobianFactor expected(ordering["x1"], Ax1, ordering["l1"], Al1, b, probModel1); JacobianFactor expected(ordering["x1"], Ax1, ordering["l1"], Al1, b, probModel1);
JacobianFactor::shared_ptr actual = factor->linearize(config, ordering); JacobianFactor::shared_ptr actual =
boost::dynamic_pointer_cast<JacobianFactor>(factor->linearize(config, ordering));
CHECK(assert_equal(expected,*actual,1e-3)); CHECK(assert_equal(expected,*actual,1e-3));
// linearize graph // linearize graph
Graph graph; Graph graph;
graph.push_back(factor); graph.push_back(factor);
FactorGraph<JacobianFactor> expected_lfg; FactorGraph<GaussianFactor> expected_lfg;
expected_lfg.push_back(actual); expected_lfg.push_back(actual);
boost::shared_ptr<FactorGraph<JacobianFactor> > actual_lfg = graph.linearize(config, ordering); boost::shared_ptr<FactorGraph<GaussianFactor> > actual_lfg = graph.linearize(config, ordering);
CHECK(assert_equal(expected_lfg,*actual_lfg)); CHECK(assert_equal(expected_lfg,*actual_lfg));
// expmap on a config // expmap on a config

View File

@ -85,7 +85,7 @@ TEST( Inference, marginals2)
init.insert(PointKey(0), Point2(1.0,1.0)); init.insert(PointKey(0), Point2(1.0,1.0));
Ordering ordering(*fg.orderingCOLAMD(init)); Ordering ordering(*fg.orderingCOLAMD(init));
FactorGraph<JacobianFactor>::shared_ptr gfg(fg.linearize(init, ordering)); FactorGraph<GaussianFactor>::shared_ptr gfg(fg.linearize(init, ordering));
GaussianMultifrontalSolver solver(*gfg); GaussianMultifrontalSolver solver(*gfg);
solver.marginalFactor(ordering[PointKey(0)]); solver.marginalFactor(ordering[PointKey(0)]);
} }

View File

@ -50,8 +50,8 @@ TEST ( NonlinearEquality, linearization ) {
// check linearize // check linearize
SharedDiagonal constraintModel = noiseModel::Constrained::All(3); SharedDiagonal constraintModel = noiseModel::Constrained::All(3);
JacobianFactor expLF(0, eye(3), zero(3), constraintModel); JacobianFactor expLF(0, eye(3), zero(3), constraintModel);
JacobianFactor::shared_ptr actualLF = nle->linearize(linearize, *linearize.orderingArbitrary()); GaussianFactor::shared_ptr actualLF = nle->linearize(linearize, *linearize.orderingArbitrary());
EXPECT(assert_equal(*actualLF, expLF)); EXPECT(assert_equal(*actualLF, (const GaussianFactor&)expLF));
} }
/* ********************************************************************** */ /* ********************************************************************** */

View File

@ -200,13 +200,13 @@ TEST( NonlinearFactor, linearize_constraint1 )
Values config; Values config;
config.insert(simulated2D::PoseKey(1), Point2(1.0, 2.0)); config.insert(simulated2D::PoseKey(1), Point2(1.0, 2.0));
JacobianFactor::shared_ptr actual = f0->linearize(config, *config.orderingArbitrary()); GaussianFactor::shared_ptr actual = f0->linearize(config, *config.orderingArbitrary());
// create expected // create expected
Ordering ord(*config.orderingArbitrary()); Ordering ord(*config.orderingArbitrary());
Vector b = Vector_(2, 0., -3.); Vector b = Vector_(2, 0., -3.);
JacobianFactor expected(ord["x1"], eye(2), b, constraint); JacobianFactor expected(ord["x1"], eye(2), b, constraint);
CHECK(assert_equal(expected, *actual)); CHECK(assert_equal((const GaussianFactor&)expected, *actual));
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -221,13 +221,13 @@ TEST( NonlinearFactor, linearize_constraint2 )
Values config; Values config;
config.insert(simulated2D::PoseKey(1), Point2(1.0, 2.0)); config.insert(simulated2D::PoseKey(1), Point2(1.0, 2.0));
config.insert(simulated2D::PointKey(1), Point2(5.0, 4.0)); config.insert(simulated2D::PointKey(1), Point2(5.0, 4.0));
JacobianFactor::shared_ptr actual = f0.linearize(config, *config.orderingArbitrary()); GaussianFactor::shared_ptr actual = f0.linearize(config, *config.orderingArbitrary());
// create expected // create expected
Ordering ord(*config.orderingArbitrary()); Ordering ord(*config.orderingArbitrary());
Vector b = Vector_(2, -3., -3.); Vector b = Vector_(2, -3., -3.);
JacobianFactor expected(ord["x1"], -1*eye(2), ord["l1"], eye(2), b, constraint); JacobianFactor expected(ord["x1"], -1*eye(2), ord["l1"], eye(2), b, constraint);
CHECK(assert_equal(expected, *actual)); CHECK(assert_equal((const GaussianFactor&)expected, *actual));
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -96,8 +96,8 @@ TEST( Graph, linearize )
{ {
Graph fg = createNonlinearFactorGraph(); Graph fg = createNonlinearFactorGraph();
Values initial = createNoisyValues(); Values initial = createNoisyValues();
boost::shared_ptr<FactorGraph<JacobianFactor> > linearized = fg.linearize(initial, *initial.orderingArbitrary()); boost::shared_ptr<FactorGraph<GaussianFactor> > linearized = fg.linearize(initial, *initial.orderingArbitrary());
FactorGraph<JacobianFactor> expected = createGaussianFactorGraph(*initial.orderingArbitrary()); FactorGraph<GaussianFactor> expected = createGaussianFactorGraph(*initial.orderingArbitrary());
CHECK(assert_equal(expected,*linearized)); // Needs correct linearizations CHECK(assert_equal(expected,*linearized)); // Needs correct linearizations
} }