The range adaptor scheme did not work for std::map TERMS in creating a JacobianFacor. Hence, I removed it - which I think is more readable - and replaced it with an explicit creationg of dimensions. I also added a test with std::map, which works.
parent
81645cb1f4
commit
d34ba9c8bf
|
@ -19,10 +19,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gtsam/linear/linearExceptions.h>
|
#include <gtsam/linear/linearExceptions.h>
|
||||||
#include <boost/assign/list_of.hpp>
|
|
||||||
#include <boost/range/adaptor/transformed.hpp>
|
|
||||||
#include <boost/range/algorithm/for_each.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -59,20 +55,10 @@ namespace gtsam {
|
||||||
model_ = model;
|
model_ = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
namespace internal {
|
|
||||||
static inline DenseIndex getColsJF(const std::pair<Key,Matrix>& p) {
|
|
||||||
return p.second.cols();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<typename TERMS>
|
template<typename TERMS>
|
||||||
void JacobianFactor::fillTerms(const TERMS& terms, const Vector& b, const SharedDiagonal& noiseModel)
|
void JacobianFactor::fillTerms(const TERMS& terms, const Vector& b, const SharedDiagonal& noiseModel)
|
||||||
{
|
{
|
||||||
using boost::adaptors::transformed;
|
|
||||||
namespace br = boost::range;
|
|
||||||
|
|
||||||
// Check noise model dimension
|
// Check noise model dimension
|
||||||
if(noiseModel && (DenseIndex)noiseModel->dim() != b.size())
|
if(noiseModel && (DenseIndex)noiseModel->dim() != b.size())
|
||||||
throw InvalidNoiseModel(b.size(), noiseModel->dim());
|
throw InvalidNoiseModel(b.size(), noiseModel->dim());
|
||||||
|
@ -80,25 +66,31 @@ namespace gtsam {
|
||||||
// Resize base class key vector
|
// Resize base class key vector
|
||||||
Base::keys_.resize(terms.size());
|
Base::keys_.resize(terms.size());
|
||||||
|
|
||||||
// Construct block matrix - this uses the boost::range 'transformed' construct to apply
|
// Get dimensions of matrices
|
||||||
// internal::getColsJF (defined just above here in this file) to each term. This
|
std::vector<size_t> dimensions;
|
||||||
// transforms the list of terms into a list of variable dimensions, by extracting the
|
for(typename TERMS::const_iterator it = terms.begin(); it != terms.end(); ++it) {
|
||||||
// number of columns in each matrix. This is done to avoid separately allocating an
|
const std::pair<Key, Matrix>& term = *it;
|
||||||
// array of dimensions before constructing the VerticalBlockMatrix.
|
const Matrix& Ai = term.second;
|
||||||
Ab_ = VerticalBlockMatrix(terms | transformed(&internal::getColsJF), b.size(), true);
|
dimensions.push_back(Ai.cols());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct block matrix
|
||||||
|
Ab_ = VerticalBlockMatrix(dimensions, b.size(), true);
|
||||||
|
|
||||||
// Check and add terms
|
// Check and add terms
|
||||||
DenseIndex i = 0; // For block index
|
DenseIndex i = 0; // For block index
|
||||||
for(typename TERMS::const_iterator termIt = terms.begin(); termIt != terms.end(); ++termIt) {
|
for(typename TERMS::const_iterator it = terms.begin(); it != terms.end(); ++it) {
|
||||||
const std::pair<Key, Matrix>& term = *termIt;
|
const std::pair<Key, Matrix>& term = *it;
|
||||||
|
Key key = term.first;
|
||||||
|
const Matrix& Ai = term.second;
|
||||||
|
|
||||||
// Check block rows
|
// Check block rows
|
||||||
if(term.second.rows() != Ab_.rows())
|
if(Ai.rows() != Ab_.rows())
|
||||||
throw InvalidMatrixBlock(Ab_.rows(), term.second.rows());
|
throw InvalidMatrixBlock(Ab_.rows(), Ai.rows());
|
||||||
|
|
||||||
// Assign key and matrix
|
// Assign key and matrix
|
||||||
Base::keys_[i] = term.first;
|
Base::keys_[i] = key;
|
||||||
Ab_(i) = term.second;
|
Ab_(i) = Ai;
|
||||||
|
|
||||||
// Increment block index
|
// Increment block index
|
||||||
++ i;
|
++ i;
|
||||||
|
|
|
@ -105,6 +105,24 @@ TEST(JacobianFactor, constructors_and_accessors)
|
||||||
EXPECT(noise == expected.get_model());
|
EXPECT(noise == expected.get_model());
|
||||||
EXPECT(noise == actual.get_model());
|
EXPECT(noise == actual.get_model());
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// Test three-term constructor with std::map
|
||||||
|
JacobianFactor expected(
|
||||||
|
boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, noise);
|
||||||
|
map<Key,Matrix> mapTerms;
|
||||||
|
// note order of insertion plays no role: order will be determined by keys
|
||||||
|
mapTerms.insert(terms[2]);
|
||||||
|
mapTerms.insert(terms[1]);
|
||||||
|
mapTerms.insert(terms[0]);
|
||||||
|
JacobianFactor actual(mapTerms, b, noise);
|
||||||
|
EXPECT(assert_equal(expected, actual));
|
||||||
|
LONGS_EQUAL((long)terms[2].first, (long)actual.keys().back());
|
||||||
|
EXPECT(assert_equal(terms[2].second, actual.getA(actual.end() - 1)));
|
||||||
|
EXPECT(assert_equal(b, expected.getb()));
|
||||||
|
EXPECT(assert_equal(b, actual.getb()));
|
||||||
|
EXPECT(noise == expected.get_model());
|
||||||
|
EXPECT(noise == actual.get_model());
|
||||||
|
}
|
||||||
{
|
{
|
||||||
// VerticalBlockMatrix constructor
|
// VerticalBlockMatrix constructor
|
||||||
JacobianFactor expected(
|
JacobianFactor expected(
|
||||||
|
|
Loading…
Reference in New Issue