Only ExpressionFactor needs dimensions! Also, add dimensions at construction -> speeds up linearize.
parent
3413b98331
commit
944422e295
|
@ -34,51 +34,42 @@ class Expression {
|
|||
private:
|
||||
|
||||
// Paul's trick shared pointer, polymorphic root of entire expression tree
|
||||
const boost::shared_ptr<ExpressionNode<T> > root_;
|
||||
|
||||
// Fixed dimensions: an Expression is assumed unmutable
|
||||
const std::vector<size_t> dimensions_;
|
||||
boost::shared_ptr<ExpressionNode<T> > root_;
|
||||
|
||||
public:
|
||||
|
||||
// Construct a constant expression
|
||||
Expression(const T& value) :
|
||||
root_(new ConstantExpression<T>(value)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
root_(new ConstantExpression<T>(value)) {
|
||||
}
|
||||
|
||||
// Construct a leaf expression, with Key
|
||||
Expression(const Key& key) :
|
||||
root_(new LeafExpression<T>(key)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
root_(new LeafExpression<T>(key)) {
|
||||
}
|
||||
|
||||
// Construct a leaf expression, with Symbol
|
||||
Expression(const Symbol& symbol) :
|
||||
root_(new LeafExpression<T>(symbol)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
root_(new LeafExpression<T>(symbol)) {
|
||||
}
|
||||
|
||||
// Construct a leaf expression, creating Symbol
|
||||
Expression(unsigned char c, size_t j) :
|
||||
root_(new LeafExpression<T>(Symbol(c, j))), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
root_(new LeafExpression<T>(Symbol(c, j))) {
|
||||
}
|
||||
|
||||
/// Construct a nullary method expression
|
||||
template<typename A>
|
||||
Expression(const Expression<A>& expression,
|
||||
T (A::*method)(typename Optional<T, A>::type) const) :
|
||||
root_(new UnaryExpression<T, A>(boost::bind(method, _1, _2), expression)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
root_(new UnaryExpression<T, A>(boost::bind(method, _1, _2), expression)) {
|
||||
}
|
||||
|
||||
/// Construct a unary function expression
|
||||
template<typename A>
|
||||
Expression(typename UnaryExpression<T, A>::Function function,
|
||||
const Expression<A>& expression) :
|
||||
root_(new UnaryExpression<T, A>(function, expression)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
root_(new UnaryExpression<T, A>(function, expression)) {
|
||||
}
|
||||
|
||||
/// Construct a unary method expression
|
||||
|
@ -89,8 +80,7 @@ public:
|
|||
const Expression<A2>& expression2) :
|
||||
root_(
|
||||
new BinaryExpression<T, A1, A2>(boost::bind(method, _1, _2, _3, _4),
|
||||
expression1, expression2)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
expression1, expression2)) {
|
||||
}
|
||||
|
||||
/// Construct a binary function expression
|
||||
|
@ -98,8 +88,7 @@ public:
|
|||
Expression(typename BinaryExpression<T, A1, A2>::Function function,
|
||||
const Expression<A1>& expression1, const Expression<A2>& expression2) :
|
||||
root_(
|
||||
new BinaryExpression<T, A1, A2>(function, expression1, expression2)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
new BinaryExpression<T, A1, A2>(function, expression1, expression2)) {
|
||||
}
|
||||
|
||||
/// Construct a ternary function expression
|
||||
|
@ -109,8 +98,7 @@ public:
|
|||
const Expression<A3>& expression3) :
|
||||
root_(
|
||||
new TernaryExpression<T, A1, A2, A3>(function, expression1,
|
||||
expression2, expression3)), //
|
||||
dimensions_(root_->dimensions()) {
|
||||
expression2, expression3)) {
|
||||
}
|
||||
|
||||
/// Return keys that play in this expression
|
||||
|
@ -119,8 +107,8 @@ public:
|
|||
}
|
||||
|
||||
/// Return dimensions for each argument, must be same order as keys
|
||||
const std::vector<size_t>& dimensions() const {
|
||||
return dimensions_;
|
||||
std::vector<size_t> dimensions() const {
|
||||
return root_->dimensions();
|
||||
}
|
||||
|
||||
// Return size needed for memory buffer in traceExecution
|
||||
|
|
|
@ -30,8 +30,10 @@ namespace gtsam {
|
|||
template<class T>
|
||||
class ExpressionFactor: public NoiseModelFactor {
|
||||
|
||||
const T measurement_;
|
||||
const Expression<T> expression_;
|
||||
T measurement_; ///< the measurement to be compared with the expression
|
||||
Expression<T> expression_; ///< the expression that is AD enabled
|
||||
std::vector<size_t> dimensions_; ///< dimensions of the Jacobian matrices
|
||||
size_t augmentedCols_; ///< total number of columns + 1 (for RHS)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -45,6 +47,19 @@ public:
|
|||
if (noiseModel->dim() != T::dimension)
|
||||
throw std::invalid_argument(
|
||||
"ExpressionFactor was created with a NoiseModel of incorrect dimension.");
|
||||
|
||||
// Get dimensions of Jacobian matrices
|
||||
// An Expression is assumed unmutable, so we do this now
|
||||
dimensions_ = expression_.dimensions();
|
||||
|
||||
// Add sizes to know how much memory to allocate on stack in linearize
|
||||
augmentedCols_ = std::accumulate(dimensions_.begin(), dimensions_.end(), 1);
|
||||
|
||||
#ifdef DEBUG_ExpressionFactor
|
||||
BOOST_FOREACH(size_t d, dimensions_)
|
||||
std::cout << d << " ";
|
||||
std::cout << " -> " << T::dimension << "x" << augmentedCols_ << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,16 +73,14 @@ public:
|
|||
// H should be pre-allocated
|
||||
assert(H->size()==size());
|
||||
|
||||
// Get dimensions of Jacobian matrices
|
||||
std::vector<size_t> dims = expression_.dimensions();
|
||||
|
||||
// Create and zero out blocks to be passed to expression_
|
||||
JacobianMap blocks;
|
||||
for(DenseIndex i=0;i<size();i++) {
|
||||
for (DenseIndex i = 0; i < size(); i++) {
|
||||
Matrix& Hi = H->at(i);
|
||||
Hi.resize(T::dimension, dims[i]);
|
||||
Hi.resize(T::dimension, dimensions_[i]);
|
||||
Hi.setZero(); // zero out
|
||||
Eigen::Block<Matrix> block = Hi.block(0,0,T::dimension, dims[i]);
|
||||
Eigen::Block<Matrix> block = Hi.block(0, 0, T::dimension,
|
||||
dimensions_[i]);
|
||||
blocks.insert(std::make_pair(keys_[i], block));
|
||||
}
|
||||
|
||||
|
@ -81,23 +94,18 @@ public:
|
|||
|
||||
virtual boost::shared_ptr<GaussianFactor> linearize(const Values& x) const {
|
||||
|
||||
// Construct VerticalBlockMatrix and views into it
|
||||
|
||||
// Get dimensions of Jacobian matrices
|
||||
std::vector<size_t> dims = expression_.dimensions();
|
||||
|
||||
// Allocate memory on stack and create a view on it (saves a malloc)
|
||||
size_t m1 = std::accumulate(dims.begin(),dims.end(),1);
|
||||
double memory[T::dimension*m1];
|
||||
Eigen::Map<Eigen::Matrix<double,T::dimension,Eigen::Dynamic> > matrix(memory,T::dimension,m1);
|
||||
double memory[T::dimension * augmentedCols_];
|
||||
Eigen::Map<Eigen::Matrix<double, T::dimension, Eigen::Dynamic> > //
|
||||
matrix(memory, T::dimension, augmentedCols_);
|
||||
matrix.setZero(); // zero out
|
||||
|
||||
// Construct block matrix, is of right size but un-initialized
|
||||
VerticalBlockMatrix Ab(dims, matrix, true);
|
||||
VerticalBlockMatrix Ab(dimensions_, matrix, true);
|
||||
|
||||
// Create blocks to be passed to expression_
|
||||
// Create blocks into Ab_ to be passed to expression_
|
||||
JacobianMap blocks;
|
||||
for(DenseIndex i=0;i<size();i++)
|
||||
for (DenseIndex i = 0; i < size(); i++)
|
||||
blocks.insert(std::make_pair(keys_[i], Ab(i)));
|
||||
// Evaluate error to get Jacobians and RHS vector b
|
||||
T value = expression_.value(x, blocks);
|
||||
|
|
Loading…
Reference in New Issue