added raw memory access version of hessianDiagonal
parent
d2b6b12bba
commit
6edd3f10fc
|
@ -57,63 +57,56 @@ using namespace boost::assign;
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor() :
|
JacobianFactor::JacobianFactor() :
|
||||||
Ab_(cref_list_of<1>(1), 0)
|
Ab_(cref_list_of<1>(1), 0) {
|
||||||
{
|
|
||||||
getb().setZero();
|
getb().setZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor(const GaussianFactor& gf) {
|
JacobianFactor::JacobianFactor(const GaussianFactor& gf) {
|
||||||
// Copy the matrix data depending on what type of factor we're copying from
|
// Copy the matrix data depending on what type of factor we're copying from
|
||||||
if(const JacobianFactor* rhs = dynamic_cast<const JacobianFactor*>(&gf))
|
if (const JacobianFactor* rhs = dynamic_cast<const JacobianFactor*>(&gf))
|
||||||
*this = JacobianFactor(*rhs);
|
*this = JacobianFactor(*rhs);
|
||||||
else if(const HessianFactor* rhs = dynamic_cast<const HessianFactor*>(&gf))
|
else if (const HessianFactor* rhs = dynamic_cast<const HessianFactor*>(&gf))
|
||||||
*this = JacobianFactor(*rhs);
|
*this = JacobianFactor(*rhs);
|
||||||
else
|
else
|
||||||
throw std::invalid_argument("In JacobianFactor(const GaussianFactor& rhs), rhs is neither a JacobianFactor nor a HessianFactor");
|
throw std::invalid_argument(
|
||||||
}
|
"In JacobianFactor(const GaussianFactor& rhs), rhs is neither a JacobianFactor nor a HessianFactor");
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor(const Vector& b_in) :
|
JacobianFactor::JacobianFactor(const Vector& b_in) :
|
||||||
Ab_(cref_list_of<1>(1), b_in.size())
|
Ab_(cref_list_of<1>(1), b_in.size()) {
|
||||||
{
|
|
||||||
getb() = b_in;
|
getb() = b_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor(Key i1, const Matrix& A1,
|
JacobianFactor::JacobianFactor(Key i1, const Matrix& A1, const Vector& b,
|
||||||
const Vector& b, const SharedDiagonal& model)
|
const SharedDiagonal& model) {
|
||||||
{
|
|
||||||
fillTerms(cref_list_of<1>(make_pair(i1, A1)), b, model);
|
fillTerms(cref_list_of<1>(make_pair(i1, A1)), b, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor(
|
JacobianFactor::JacobianFactor(const Key i1, const Matrix& A1, Key i2,
|
||||||
const Key i1, const Matrix& A1, Key i2, const Matrix& A2,
|
const Matrix& A2, const Vector& b, const SharedDiagonal& model) {
|
||||||
const Vector& b, const SharedDiagonal& model)
|
fillTerms(cref_list_of<2>(make_pair(i1, A1))(make_pair(i2, A2)), b, model);
|
||||||
{
|
}
|
||||||
fillTerms(cref_list_of<2>
|
|
||||||
(make_pair(i1,A1))
|
|
||||||
(make_pair(i2,A2)), b, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor(
|
JacobianFactor::JacobianFactor(const Key i1, const Matrix& A1, Key i2,
|
||||||
const Key i1, const Matrix& A1, Key i2, const Matrix& A2,
|
const Matrix& A2, Key i3, const Matrix& A3, const Vector& b,
|
||||||
Key i3, const Matrix& A3, const Vector& b, const SharedDiagonal& model)
|
const SharedDiagonal& model) {
|
||||||
{
|
fillTerms(
|
||||||
fillTerms(cref_list_of<3>
|
cref_list_of<3>(make_pair(i1, A1))(make_pair(i2, A2))(make_pair(i3, A3)),
|
||||||
(make_pair(i1,A1))
|
b, model);
|
||||||
(make_pair(i2,A2))
|
}
|
||||||
(make_pair(i3,A3)), b, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor(const HessianFactor& factor) :
|
JacobianFactor::JacobianFactor(const HessianFactor& factor) :
|
||||||
Base(factor), Ab_(VerticalBlockMatrix::LikeActiveViewOf(factor.matrixObject(), factor.rows()))
|
Base(factor), Ab_(
|
||||||
{
|
VerticalBlockMatrix::LikeActiveViewOf(factor.matrixObject(),
|
||||||
|
factor.rows())) {
|
||||||
// Copy Hessian into our matrix and then do in-place Cholesky
|
// Copy Hessian into our matrix and then do in-place Cholesky
|
||||||
Ab_.full() = factor.matrixObject().full();
|
Ab_.full() = factor.matrixObject().full();
|
||||||
|
|
||||||
|
@ -123,7 +116,7 @@ namespace gtsam {
|
||||||
boost::tie(maxrank, success) = choleskyCareful(Ab_.matrix());
|
boost::tie(maxrank, success) = choleskyCareful(Ab_.matrix());
|
||||||
|
|
||||||
// Check for indefinite system
|
// Check for indefinite system
|
||||||
if(!success)
|
if (!success)
|
||||||
throw IndeterminantLinearSystemException(factor.keys().front());
|
throw IndeterminantLinearSystemException(factor.keys().front());
|
||||||
|
|
||||||
// Zero out lower triangle
|
// Zero out lower triangle
|
||||||
|
@ -132,37 +125,39 @@ namespace gtsam {
|
||||||
// FIXME: replace with triangular system
|
// FIXME: replace with triangular system
|
||||||
Ab_.rowEnd() = maxrank;
|
Ab_.rowEnd() = maxrank;
|
||||||
model_ = SharedDiagonal(); // should be same as Unit::Create(maxrank);
|
model_ = SharedDiagonal(); // should be same as Unit::Create(maxrank);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// Helper functions for combine constructor
|
// Helper functions for combine constructor
|
||||||
namespace {
|
namespace {
|
||||||
boost::tuple<FastVector<DenseIndex>, DenseIndex, DenseIndex> _countDims(
|
boost::tuple<FastVector<DenseIndex>, DenseIndex, DenseIndex> _countDims(
|
||||||
const FastVector<JacobianFactor::shared_ptr>& factors, const FastVector<VariableSlots::const_iterator>& variableSlots)
|
const FastVector<JacobianFactor::shared_ptr>& factors,
|
||||||
{
|
const FastVector<VariableSlots::const_iterator>& variableSlots) {
|
||||||
gttic(countDims);
|
gttic(countDims);
|
||||||
#ifdef GTSAM_EXTRA_CONSISTENCY_CHECKS
|
#ifdef GTSAM_EXTRA_CONSISTENCY_CHECKS
|
||||||
FastVector<DenseIndex> varDims(variableSlots.size(), numeric_limits<DenseIndex>::max());
|
FastVector<DenseIndex> varDims(variableSlots.size(), numeric_limits<DenseIndex>::max());
|
||||||
#else
|
#else
|
||||||
FastVector<DenseIndex> varDims(variableSlots.size(), numeric_limits<DenseIndex>::max());
|
FastVector<DenseIndex> varDims(variableSlots.size(),
|
||||||
|
numeric_limits<DenseIndex>::max());
|
||||||
#endif
|
#endif
|
||||||
DenseIndex m = 0;
|
DenseIndex m = 0;
|
||||||
DenseIndex n = 0;
|
DenseIndex n = 0;
|
||||||
for(size_t jointVarpos = 0; jointVarpos < variableSlots.size(); ++jointVarpos)
|
for (size_t jointVarpos = 0; jointVarpos < variableSlots.size();
|
||||||
{
|
++jointVarpos) {
|
||||||
const VariableSlots::const_iterator& slots = variableSlots[jointVarpos];
|
const VariableSlots::const_iterator& slots = variableSlots[jointVarpos];
|
||||||
|
|
||||||
assert(slots->second.size() == factors.size());
|
assert(slots->second.size() == factors.size());
|
||||||
|
|
||||||
bool foundVariable = false;
|
bool foundVariable = false;
|
||||||
for(size_t sourceFactorI = 0; sourceFactorI < slots->second.size(); ++sourceFactorI)
|
for (size_t sourceFactorI = 0; sourceFactorI < slots->second.size();
|
||||||
{
|
++sourceFactorI) {
|
||||||
const size_t sourceVarpos = slots->second[sourceFactorI];
|
const size_t sourceVarpos = slots->second[sourceFactorI];
|
||||||
if(sourceVarpos != VariableSlots::Empty) {
|
if (sourceVarpos != VariableSlots::Empty) {
|
||||||
const JacobianFactor& sourceFactor = *factors[sourceFactorI];
|
const JacobianFactor& sourceFactor = *factors[sourceFactorI];
|
||||||
if(sourceFactor.cols() > 1) {
|
if (sourceFactor.cols() > 1) {
|
||||||
foundVariable = true;
|
foundVariable = true;
|
||||||
DenseIndex vardim = sourceFactor.getDim(sourceFactor.begin() + sourceVarpos);
|
DenseIndex vardim = sourceFactor.getDim(
|
||||||
|
sourceFactor.begin() + sourceVarpos);
|
||||||
|
|
||||||
#ifdef GTSAM_EXTRA_CONSISTENCY_CHECKS
|
#ifdef GTSAM_EXTRA_CONSISTENCY_CHECKS
|
||||||
if(varDims[jointVarpos] == numeric_limits<DenseIndex>::max()) {
|
if(varDims[jointVarpos] == numeric_limits<DenseIndex>::max()) {
|
||||||
|
@ -185,8 +180,9 @@ namespace gtsam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!foundVariable)
|
if (!foundVariable)
|
||||||
throw std::invalid_argument("Unable to determine dimensionality for all variables");
|
throw std::invalid_argument(
|
||||||
|
"Unable to determine dimensionality for all variables");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(const JacobianFactor::shared_ptr& factor, factors) {
|
BOOST_FOREACH(const JacobianFactor::shared_ptr& factor, factors) {
|
||||||
|
@ -200,44 +196,43 @@ namespace gtsam {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return boost::make_tuple(varDims, m, n);
|
return boost::make_tuple(varDims, m, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
FastVector<JacobianFactor::shared_ptr>
|
FastVector<JacobianFactor::shared_ptr> _convertOrCastToJacobians(
|
||||||
_convertOrCastToJacobians(const GaussianFactorGraph& factors)
|
const GaussianFactorGraph& factors) {
|
||||||
{
|
|
||||||
gttic(Convert_to_Jacobians);
|
gttic(Convert_to_Jacobians);
|
||||||
FastVector<JacobianFactor::shared_ptr> jacobians;
|
FastVector<JacobianFactor::shared_ptr> jacobians;
|
||||||
jacobians.reserve(factors.size());
|
jacobians.reserve(factors.size());
|
||||||
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, factors) {
|
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, factors) {
|
||||||
if(factor) {
|
if (factor) {
|
||||||
if(JacobianFactor::shared_ptr jf = boost::dynamic_pointer_cast<JacobianFactor>(factor))
|
if (JacobianFactor::shared_ptr jf = boost::dynamic_pointer_cast<
|
||||||
|
JacobianFactor>(factor))
|
||||||
jacobians.push_back(jf);
|
jacobians.push_back(jf);
|
||||||
else
|
else
|
||||||
jacobians.push_back(boost::make_shared<JacobianFactor>(*factor));
|
jacobians.push_back(boost::make_shared<JacobianFactor>(*factor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return jacobians;
|
return jacobians;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor::JacobianFactor(
|
JacobianFactor::JacobianFactor(const GaussianFactorGraph& graph,
|
||||||
const GaussianFactorGraph& graph,
|
|
||||||
boost::optional<const Ordering&> ordering,
|
boost::optional<const Ordering&> ordering,
|
||||||
boost::optional<const VariableSlots&> variableSlots)
|
boost::optional<const VariableSlots&> variableSlots) {
|
||||||
{
|
|
||||||
gttic(JacobianFactor_combine_constructor);
|
gttic(JacobianFactor_combine_constructor);
|
||||||
|
|
||||||
// Compute VariableSlots if one was not provided
|
// Compute VariableSlots if one was not provided
|
||||||
boost::optional<VariableSlots> computedVariableSlots;
|
boost::optional<VariableSlots> computedVariableSlots;
|
||||||
if(!variableSlots) {
|
if (!variableSlots) {
|
||||||
computedVariableSlots = VariableSlots(graph);
|
computedVariableSlots = VariableSlots(graph);
|
||||||
variableSlots = computedVariableSlots; // Binds reference, does not copy VariableSlots
|
variableSlots = computedVariableSlots; // Binds reference, does not copy VariableSlots
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast or convert to Jacobians
|
// Cast or convert to Jacobians
|
||||||
FastVector<JacobianFactor::shared_ptr> jacobians = _convertOrCastToJacobians(graph);
|
FastVector<JacobianFactor::shared_ptr> jacobians = _convertOrCastToJacobians(
|
||||||
|
graph);
|
||||||
|
|
||||||
gttic(Order_slots);
|
gttic(Order_slots);
|
||||||
// Order variable slots - we maintain the vector of ordered slots, as well as keep a list
|
// Order variable slots - we maintain the vector of ordered slots, as well as keep a list
|
||||||
|
@ -245,22 +240,24 @@ namespace gtsam {
|
||||||
// be added after all of the ordered variables.
|
// be added after all of the ordered variables.
|
||||||
FastVector<VariableSlots::const_iterator> orderedSlots;
|
FastVector<VariableSlots::const_iterator> orderedSlots;
|
||||||
orderedSlots.reserve(variableSlots->size());
|
orderedSlots.reserve(variableSlots->size());
|
||||||
if(ordering) {
|
if (ordering) {
|
||||||
// If an ordering is provided, arrange the slots first that ordering
|
// If an ordering is provided, arrange the slots first that ordering
|
||||||
FastList<VariableSlots::const_iterator> unorderedSlots;
|
FastList<VariableSlots::const_iterator> unorderedSlots;
|
||||||
size_t nOrderingSlotsUsed = 0;
|
size_t nOrderingSlotsUsed = 0;
|
||||||
orderedSlots.resize(ordering->size());
|
orderedSlots.resize(ordering->size());
|
||||||
FastMap<Key, size_t> inverseOrdering = ordering->invert();
|
FastMap<Key, size_t> inverseOrdering = ordering->invert();
|
||||||
for(VariableSlots::const_iterator item = variableSlots->begin(); item != variableSlots->end(); ++item) {
|
for (VariableSlots::const_iterator item = variableSlots->begin();
|
||||||
FastMap<Key, size_t>::const_iterator orderingPosition = inverseOrdering.find(item->first);
|
item != variableSlots->end(); ++item) {
|
||||||
if(orderingPosition == inverseOrdering.end()) {
|
FastMap<Key, size_t>::const_iterator orderingPosition =
|
||||||
|
inverseOrdering.find(item->first);
|
||||||
|
if (orderingPosition == inverseOrdering.end()) {
|
||||||
unorderedSlots.push_back(item);
|
unorderedSlots.push_back(item);
|
||||||
} else {
|
} else {
|
||||||
orderedSlots[orderingPosition->second] = item;
|
orderedSlots[orderingPosition->second] = item;
|
||||||
++ nOrderingSlotsUsed;
|
++nOrderingSlotsUsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(nOrderingSlotsUsed != ordering->size())
|
if (nOrderingSlotsUsed != ordering->size())
|
||||||
throw std::invalid_argument(
|
throw std::invalid_argument(
|
||||||
"The ordering provided to the JacobianFactor combine constructor\n"
|
"The ordering provided to the JacobianFactor combine constructor\n"
|
||||||
"contained extra variables that did not appear in the factors to combine.");
|
"contained extra variables that did not appear in the factors to combine.");
|
||||||
|
@ -271,7 +268,8 @@ namespace gtsam {
|
||||||
} else {
|
} else {
|
||||||
// If no ordering is provided, arrange the slots as they were, which will be sorted
|
// If no ordering is provided, arrange the slots as they were, which will be sorted
|
||||||
// numerically since VariableSlots uses a map sorting on Key.
|
// numerically since VariableSlots uses a map sorting on Key.
|
||||||
for(VariableSlots::const_iterator item = variableSlots->begin(); item != variableSlots->end(); ++item)
|
for (VariableSlots::const_iterator item = variableSlots->begin();
|
||||||
|
item != variableSlots->end(); ++item)
|
||||||
orderedSlots.push_back(item);
|
orderedSlots.push_back(item);
|
||||||
}
|
}
|
||||||
gttoc(Order_slots);
|
gttoc(Order_slots);
|
||||||
|
@ -285,26 +283,30 @@ namespace gtsam {
|
||||||
gttic(allocate);
|
gttic(allocate);
|
||||||
Ab_ = VerticalBlockMatrix(varDims, m, true); // Allocate augmented matrix
|
Ab_ = VerticalBlockMatrix(varDims, m, true); // Allocate augmented matrix
|
||||||
Base::keys_.resize(orderedSlots.size());
|
Base::keys_.resize(orderedSlots.size());
|
||||||
boost::range::copy( // Get variable keys
|
boost::range::copy(
|
||||||
orderedSlots | boost::adaptors::indirected | boost::adaptors::map_keys, Base::keys_.begin());
|
// Get variable keys
|
||||||
|
orderedSlots | boost::adaptors::indirected | boost::adaptors::map_keys,
|
||||||
|
Base::keys_.begin());
|
||||||
gttoc(allocate);
|
gttoc(allocate);
|
||||||
|
|
||||||
// Loop over slots in combined factor and copy blocks from source factors
|
// Loop over slots in combined factor and copy blocks from source factors
|
||||||
gttic(copy_blocks);
|
gttic(copy_blocks);
|
||||||
size_t combinedSlot = 0;
|
size_t combinedSlot = 0;
|
||||||
BOOST_FOREACH(VariableSlots::const_iterator varslot, orderedSlots) {
|
BOOST_FOREACH(VariableSlots::const_iterator varslot, orderedSlots) {
|
||||||
JacobianFactor::ABlock destSlot(this->getA(this->begin()+combinedSlot));
|
JacobianFactor::ABlock destSlot(this->getA(this->begin() + combinedSlot));
|
||||||
// Loop over source jacobians
|
// Loop over source jacobians
|
||||||
DenseIndex nextRow = 0;
|
DenseIndex nextRow = 0;
|
||||||
for(size_t factorI = 0; factorI < jacobians.size(); ++factorI) {
|
for (size_t factorI = 0; factorI < jacobians.size(); ++factorI) {
|
||||||
// Slot in source factor
|
// Slot in source factor
|
||||||
const size_t sourceSlot = varslot->second[factorI];
|
const size_t sourceSlot = varslot->second[factorI];
|
||||||
const DenseIndex sourceRows = jacobians[factorI]->rows();
|
const DenseIndex sourceRows = jacobians[factorI]->rows();
|
||||||
if(sourceRows > 0) {
|
if (sourceRows > 0) {
|
||||||
JacobianFactor::ABlock::RowsBlockXpr destBlock(destSlot.middleRows(nextRow, sourceRows));
|
JacobianFactor::ABlock::RowsBlockXpr destBlock(
|
||||||
|
destSlot.middleRows(nextRow, sourceRows));
|
||||||
// Copy if exists in source factor, otherwise set zero
|
// Copy if exists in source factor, otherwise set zero
|
||||||
if(sourceSlot != VariableSlots::Empty)
|
if (sourceSlot != VariableSlots::Empty)
|
||||||
destBlock = jacobians[factorI]->getA(jacobians[factorI]->begin()+sourceSlot);
|
destBlock = jacobians[factorI]->getA(
|
||||||
|
jacobians[factorI]->begin() + sourceSlot);
|
||||||
else
|
else
|
||||||
destBlock.setZero();
|
destBlock.setZero();
|
||||||
nextRow += sourceRows;
|
nextRow += sourceRows;
|
||||||
|
@ -320,15 +322,16 @@ namespace gtsam {
|
||||||
boost::optional<Vector> sigmas;
|
boost::optional<Vector> sigmas;
|
||||||
// Loop over source jacobians
|
// Loop over source jacobians
|
||||||
DenseIndex nextRow = 0;
|
DenseIndex nextRow = 0;
|
||||||
for(size_t factorI = 0; factorI < jacobians.size(); ++factorI) {
|
for (size_t factorI = 0; factorI < jacobians.size(); ++factorI) {
|
||||||
const DenseIndex sourceRows = jacobians[factorI]->rows();
|
const DenseIndex sourceRows = jacobians[factorI]->rows();
|
||||||
if(sourceRows > 0) {
|
if (sourceRows > 0) {
|
||||||
this->getb().segment(nextRow, sourceRows) = jacobians[factorI]->getb();
|
this->getb().segment(nextRow, sourceRows) = jacobians[factorI]->getb();
|
||||||
if(jacobians[factorI]->get_model()) {
|
if (jacobians[factorI]->get_model()) {
|
||||||
// If the factor has a noise model and we haven't yet allocated sigmas, allocate it.
|
// If the factor has a noise model and we haven't yet allocated sigmas, allocate it.
|
||||||
if(!sigmas)
|
if (!sigmas)
|
||||||
sigmas = Vector::Constant(m, 1.0);
|
sigmas = Vector::Constant(m, 1.0);
|
||||||
sigmas->segment(nextRow, sourceRows) = jacobians[factorI]->get_model()->sigmas();
|
sigmas->segment(nextRow, sourceRows) =
|
||||||
|
jacobians[factorI]->get_model()->sigmas();
|
||||||
if (jacobians[factorI]->isConstrained())
|
if (jacobians[factorI]->isConstrained())
|
||||||
anyConstrained = true;
|
anyConstrained = true;
|
||||||
}
|
}
|
||||||
|
@ -337,44 +340,44 @@ namespace gtsam {
|
||||||
}
|
}
|
||||||
gttoc(copy_vectors);
|
gttoc(copy_vectors);
|
||||||
|
|
||||||
if(sigmas)
|
if (sigmas)
|
||||||
this->setModel(anyConstrained, *sigmas);
|
this->setModel(anyConstrained, *sigmas);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void JacobianFactor::print(const string& s, const KeyFormatter& formatter) const
|
void JacobianFactor::print(const string& s,
|
||||||
{
|
const KeyFormatter& formatter) const {
|
||||||
if(!s.empty())
|
if (!s.empty())
|
||||||
cout << s << "\n";
|
cout << s << "\n";
|
||||||
for(const_iterator key = begin(); key != end(); ++key) {
|
for (const_iterator key = begin(); key != end(); ++key) {
|
||||||
cout <<
|
cout
|
||||||
formatMatrixIndented((boost::format(" A[%1%] = ") % formatter(*key)).str(), getA(key))
|
<< formatMatrixIndented(
|
||||||
|
(boost::format(" A[%1%] = ") % formatter(*key)).str(), getA(key))
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
cout << formatMatrixIndented(" b = ", getb(), true) << "\n";
|
cout << formatMatrixIndented(" b = ", getb(), true) << "\n";
|
||||||
if(model_)
|
if (model_)
|
||||||
model_->print(" Noise model: ");
|
model_->print(" Noise model: ");
|
||||||
else
|
else
|
||||||
cout << " No noise model" << endl;
|
cout << " No noise model" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// Check if two linear factors are equal
|
// Check if two linear factors are equal
|
||||||
bool JacobianFactor::equals(const GaussianFactor& f_, double tol) const
|
bool JacobianFactor::equals(const GaussianFactor& f_, double tol) const {
|
||||||
{
|
if (!dynamic_cast<const JacobianFactor*>(&f_))
|
||||||
if(!dynamic_cast<const JacobianFactor*>(&f_))
|
|
||||||
return false;
|
return false;
|
||||||
else {
|
else {
|
||||||
const JacobianFactor& f(static_cast<const JacobianFactor&>(f_));
|
const JacobianFactor& f(static_cast<const JacobianFactor&>(f_));
|
||||||
|
|
||||||
// Check keys
|
// Check keys
|
||||||
if(keys() != f.keys())
|
if (keys() != f.keys())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check noise model
|
// Check noise model
|
||||||
if((model_ && !f.model_) || (!model_ && f.model_))
|
if ((model_ && !f.model_) || (!model_ && f.model_))
|
||||||
return false;
|
return false;
|
||||||
if(model_ && f.model_ && !model_->equals(*f.model_, tol))
|
if (model_ && f.model_ && !model_->equals(*f.model_, tol))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check matrix sizes
|
// Check matrix sizes
|
||||||
|
@ -384,161 +387,183 @@ namespace gtsam {
|
||||||
// Check matrix contents
|
// Check matrix contents
|
||||||
constABlock Ab1(Ab_.range(0, Ab_.nBlocks()));
|
constABlock Ab1(Ab_.range(0, Ab_.nBlocks()));
|
||||||
constABlock Ab2(f.Ab_.range(0, f.Ab_.nBlocks()));
|
constABlock Ab2(f.Ab_.range(0, f.Ab_.nBlocks()));
|
||||||
for(size_t row=0; row< (size_t) Ab1.rows(); ++row)
|
for (size_t row = 0; row < (size_t) Ab1.rows(); ++row)
|
||||||
if(!equal_with_abs_tol(Ab1.row(row), Ab2.row(row), tol) &&
|
if (!equal_with_abs_tol(Ab1.row(row), Ab2.row(row), tol)
|
||||||
!equal_with_abs_tol(-Ab1.row(row), Ab2.row(row), tol))
|
&& !equal_with_abs_tol(-Ab1.row(row), Ab2.row(row), tol))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Vector JacobianFactor::unweighted_error(const VectorValues& c) const {
|
Vector JacobianFactor::unweighted_error(const VectorValues& c) const {
|
||||||
Vector e = -getb();
|
Vector e = -getb();
|
||||||
for(size_t pos=0; pos<size(); ++pos)
|
for (size_t pos = 0; pos < size(); ++pos)
|
||||||
e += Ab_(pos) * c[keys_[pos]];
|
e += Ab_(pos) * c[keys_[pos]];
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Vector JacobianFactor::error_vector(const VectorValues& c) const {
|
Vector JacobianFactor::error_vector(const VectorValues& c) const {
|
||||||
if(model_)
|
if (model_)
|
||||||
return model_->whiten(unweighted_error(c));
|
return model_->whiten(unweighted_error(c));
|
||||||
else
|
else
|
||||||
return unweighted_error(c);
|
return unweighted_error(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
double JacobianFactor::error(const VectorValues& c) const {
|
double JacobianFactor::error(const VectorValues& c) const {
|
||||||
if (empty()) return 0;
|
if (empty())
|
||||||
|
return 0;
|
||||||
Vector weighted = error_vector(c);
|
Vector weighted = error_vector(c);
|
||||||
return 0.5 * weighted.dot(weighted);
|
return 0.5 * weighted.dot(weighted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Matrix JacobianFactor::augmentedInformation() const {
|
Matrix JacobianFactor::augmentedInformation() const {
|
||||||
if(model_) {
|
if (model_) {
|
||||||
Matrix AbWhitened = Ab_.full();
|
Matrix AbWhitened = Ab_.full();
|
||||||
model_->WhitenInPlace(AbWhitened);
|
model_->WhitenInPlace(AbWhitened);
|
||||||
return AbWhitened.transpose() * AbWhitened;
|
return AbWhitened.transpose() * AbWhitened;
|
||||||
} else {
|
} else {
|
||||||
return Ab_.full().transpose() * Ab_.full();
|
return Ab_.full().transpose() * Ab_.full();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Matrix JacobianFactor::information() const {
|
Matrix JacobianFactor::information() const {
|
||||||
if(model_) {
|
if (model_) {
|
||||||
Matrix AWhitened = this->getA();
|
Matrix AWhitened = this->getA();
|
||||||
model_->WhitenInPlace(AWhitened);
|
model_->WhitenInPlace(AWhitened);
|
||||||
return AWhitened.transpose() * AWhitened;
|
return AWhitened.transpose() * AWhitened;
|
||||||
} else {
|
} else {
|
||||||
return this->getA().transpose() * this->getA();
|
return this->getA().transpose() * this->getA();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
VectorValues JacobianFactor::hessianDiagonal() const {
|
VectorValues JacobianFactor::hessianDiagonal() const {
|
||||||
VectorValues d;
|
VectorValues d;
|
||||||
for(size_t pos=0; pos<size(); ++pos)
|
for (size_t pos = 0; pos < size(); ++pos) {
|
||||||
{
|
|
||||||
Key j = keys_[pos];
|
Key j = keys_[pos];
|
||||||
size_t nj = Ab_(pos).cols();
|
size_t nj = Ab_(pos).cols();
|
||||||
Vector dj(nj);
|
Vector dj(nj);
|
||||||
for (size_t k = 0; k < nj; ++k) {
|
for (size_t k = 0; k < nj; ++k) {
|
||||||
Vector column_k = Ab_(pos).col(k);
|
Vector column_k = Ab_(pos).col(k);
|
||||||
if (model_) column_k = model_->whiten(column_k);
|
if (model_)
|
||||||
dj(k) = dot(column_k,column_k);
|
column_k = model_->whiten(column_k);
|
||||||
|
dj(k) = dot(column_k, column_k);
|
||||||
}
|
}
|
||||||
d.insert(j,dj);
|
d.insert(j, dj);
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void JacobianFactor::hessianDiagonal(double* d) const {
|
// TODO: currently assumes all variables of the same size 9 and keys arranged from 0 to n
|
||||||
throw std::runtime_error("JacobianFactor::hessianDiagonal non implemented (use VectorValues version)");
|
void JacobianFactor::hessianDiagonal(double* d) const {
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
// Use eigen magic to access raw memory
|
||||||
map<Key,Matrix> JacobianFactor::hessianBlockDiagonal() const {
|
typedef Eigen::Matrix<double, 9, 1> DVector;
|
||||||
map<Key,Matrix> blocks;
|
typedef Eigen::Map<DVector> DMap;
|
||||||
for(size_t pos=0; pos<size(); ++pos)
|
|
||||||
{
|
// Loop over all variables in the factor
|
||||||
|
for (DenseIndex j = 0; j < (DenseIndex) size(); ++j) {
|
||||||
|
// Get the diagonal block, and insert its diagonal
|
||||||
|
DVector dj;
|
||||||
|
for (size_t k = 0; k < 9; ++k)
|
||||||
|
dj(k) = Ab_(j).col(k).squaredNorm();
|
||||||
|
|
||||||
|
DMap(d + 9 * j) += dj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
map<Key, Matrix> JacobianFactor::hessianBlockDiagonal() const {
|
||||||
|
map<Key, Matrix> blocks;
|
||||||
|
for (size_t pos = 0; pos < size(); ++pos) {
|
||||||
Key j = keys_[pos];
|
Key j = keys_[pos];
|
||||||
Matrix Aj = Ab_(pos);
|
Matrix Aj = Ab_(pos);
|
||||||
if (model_) Aj = model_->Whiten(Aj);
|
if (model_)
|
||||||
blocks.insert(make_pair(j,Aj.transpose()*Aj));
|
Aj = model_->Whiten(Aj);
|
||||||
|
blocks.insert(make_pair(j, Aj.transpose() * Aj));
|
||||||
}
|
}
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Vector JacobianFactor::operator*(const VectorValues& x) const {
|
Vector JacobianFactor::operator*(const VectorValues& x) const {
|
||||||
Vector Ax = zero(Ab_.rows());
|
Vector Ax = zero(Ab_.rows());
|
||||||
if (empty()) return Ax;
|
if (empty())
|
||||||
|
return Ax;
|
||||||
|
|
||||||
// Just iterate over all A matrices and multiply in correct config part
|
// Just iterate over all A matrices and multiply in correct config part
|
||||||
for(size_t pos=0; pos<size(); ++pos)
|
for (size_t pos = 0; pos < size(); ++pos)
|
||||||
Ax += Ab_(pos) * x[keys_[pos]];
|
Ax += Ab_(pos) * x[keys_[pos]];
|
||||||
|
|
||||||
return model_ ? model_->whiten(Ax) : Ax;
|
return model_ ? model_->whiten(Ax) : Ax;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void JacobianFactor::transposeMultiplyAdd(double alpha, const Vector& e,
|
void JacobianFactor::transposeMultiplyAdd(double alpha, const Vector& e,
|
||||||
VectorValues& x) const
|
VectorValues& x) const {
|
||||||
{
|
|
||||||
Vector E = alpha * (model_ ? model_->whiten(e) : e);
|
Vector E = alpha * (model_ ? model_->whiten(e) : e);
|
||||||
// Just iterate over all A matrices and insert Ai^e into VectorValues
|
// Just iterate over all A matrices and insert Ai^e into VectorValues
|
||||||
for(size_t pos=0; pos<size(); ++pos)
|
for (size_t pos = 0; pos < size(); ++pos) {
|
||||||
{
|
|
||||||
Key j = keys_[pos];
|
Key j = keys_[pos];
|
||||||
// Create the value as a zero vector if it does not exist.
|
// Create the value as a zero vector if it does not exist.
|
||||||
pair<VectorValues::iterator, bool> xi = x.tryInsert(j, Vector());
|
pair<VectorValues::iterator, bool> xi = x.tryInsert(j, Vector());
|
||||||
if(xi.second)
|
if (xi.second)
|
||||||
xi.first->second = Vector::Zero(getDim(begin() + pos));
|
xi.first->second = Vector::Zero(getDim(begin() + pos));
|
||||||
gtsam::transposeMultiplyAdd(Ab_(pos), E, xi.first->second);
|
gtsam::transposeMultiplyAdd(Ab_(pos), E, xi.first->second);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void JacobianFactor::multiplyHessianAdd(double alpha, const VectorValues& x,
|
void JacobianFactor::multiplyHessianAdd(double alpha, const VectorValues& x,
|
||||||
VectorValues& y) const {
|
VectorValues& y) const {
|
||||||
Vector Ax = (*this)*x;
|
Vector Ax = (*this) * x;
|
||||||
transposeMultiplyAdd(alpha,Ax,y);
|
transposeMultiplyAdd(alpha, Ax, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JacobianFactor::multiplyHessianAdd(double alpha, const double* x, double* y, std::vector<size_t> keys) const {
|
void JacobianFactor::multiplyHessianAdd(double alpha, const double* x,
|
||||||
|
double* y, std::vector<size_t> keys) const {
|
||||||
|
|
||||||
// Use eigen magic to access raw memory
|
// Use eigen magic to access raw memory
|
||||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 1> DVector;
|
typedef Eigen::Matrix<double, Eigen::Dynamic, 1> DVector;
|
||||||
typedef Eigen::Map<DVector> DMap;
|
typedef Eigen::Map<DVector> DMap;
|
||||||
typedef Eigen::Map<const DVector> ConstDMap;
|
typedef Eigen::Map<const DVector> ConstDMap;
|
||||||
|
|
||||||
if (empty()) return;
|
if (empty())
|
||||||
|
return;
|
||||||
Vector Ax = zero(Ab_.rows());
|
Vector Ax = zero(Ab_.rows());
|
||||||
|
|
||||||
// Just iterate over all A matrices and multiply in correct config part
|
// Just iterate over all A matrices and multiply in correct config part
|
||||||
for(size_t pos=0; pos<size(); ++pos)
|
for (size_t pos = 0; pos < size(); ++pos)
|
||||||
Ax += Ab_(pos) * ConstDMap(x + keys[keys_[pos]],keys[keys_[pos]+1]-keys[keys_[pos]]);
|
Ax += Ab_(pos)
|
||||||
|
* ConstDMap(x + keys[keys_[pos]],
|
||||||
|
keys[keys_[pos] + 1] - keys[keys_[pos]]);
|
||||||
|
|
||||||
// Deal with noise properly, need to Double* whiten as we are dividing by variance
|
// Deal with noise properly, need to Double* whiten as we are dividing by variance
|
||||||
if (model_) { model_->whitenInPlace(Ax); model_->whitenInPlace(Ax); }
|
if (model_) {
|
||||||
|
model_->whitenInPlace(Ax);
|
||||||
|
model_->whitenInPlace(Ax);
|
||||||
|
}
|
||||||
|
|
||||||
// multiply with alpha
|
// multiply with alpha
|
||||||
Ax *= alpha;
|
Ax *= alpha;
|
||||||
|
|
||||||
// Again iterate over all A matrices and insert Ai^e into y
|
// Again iterate over all A matrices and insert Ai^e into y
|
||||||
for(size_t pos=0; pos<size(); ++pos)
|
for (size_t pos = 0; pos < size(); ++pos)
|
||||||
DMap(y + keys[keys_[pos]],keys[keys_[pos]+1]-keys[keys_[pos]]) += Ab_(pos).transpose() * Ax;
|
DMap(y + keys[keys_[pos]], keys[keys_[pos] + 1] - keys[keys_[pos]]) += Ab_(
|
||||||
|
pos).transpose() * Ax;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
VectorValues JacobianFactor::gradientAtZero() const {
|
VectorValues JacobianFactor::gradientAtZero() const {
|
||||||
VectorValues g;
|
VectorValues g;
|
||||||
Vector b = getb();
|
Vector b = getb();
|
||||||
// Gradient is really -A'*b / sigma^2
|
// Gradient is really -A'*b / sigma^2
|
||||||
|
@ -546,82 +571,82 @@ namespace gtsam {
|
||||||
Vector b_sigma = model_ ? model_->whiten(b) : b;
|
Vector b_sigma = model_ ? model_->whiten(b) : b;
|
||||||
this->transposeMultiplyAdd(-1.0, b_sigma, g); // g -= A'*b/sigma^2
|
this->transposeMultiplyAdd(-1.0, b_sigma, g); // g -= A'*b/sigma^2
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
pair<Matrix,Vector> JacobianFactor::jacobian() const {
|
pair<Matrix, Vector> JacobianFactor::jacobian() const {
|
||||||
pair<Matrix,Vector> result = jacobianUnweighted();
|
pair<Matrix, Vector> result = jacobianUnweighted();
|
||||||
// divide in sigma so error is indeed 0.5*|Ax-b|
|
// divide in sigma so error is indeed 0.5*|Ax-b|
|
||||||
if (model_)
|
if (model_)
|
||||||
model_->WhitenSystem(result.first, result.second);
|
model_->WhitenSystem(result.first, result.second);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
pair<Matrix,Vector> JacobianFactor::jacobianUnweighted() const {
|
pair<Matrix, Vector> JacobianFactor::jacobianUnweighted() const {
|
||||||
Matrix A(Ab_.range(0, size()));
|
Matrix A(Ab_.range(0, size()));
|
||||||
Vector b(getb());
|
Vector b(getb());
|
||||||
return make_pair(A, b);
|
return make_pair(A, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Matrix JacobianFactor::augmentedJacobian() const {
|
Matrix JacobianFactor::augmentedJacobian() const {
|
||||||
Matrix Ab = augmentedJacobianUnweighted();
|
Matrix Ab = augmentedJacobianUnweighted();
|
||||||
if (model_)
|
if (model_)
|
||||||
model_->WhitenInPlace(Ab);
|
model_->WhitenInPlace(Ab);
|
||||||
return Ab;
|
return Ab;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Matrix JacobianFactor::augmentedJacobianUnweighted() const {
|
Matrix JacobianFactor::augmentedJacobianUnweighted() const {
|
||||||
return Ab_.range(0, Ab_.nBlocks());
|
return Ab_.range(0, Ab_.nBlocks());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
JacobianFactor JacobianFactor::whiten() const {
|
JacobianFactor JacobianFactor::whiten() const {
|
||||||
JacobianFactor result(*this);
|
JacobianFactor result(*this);
|
||||||
if(model_) {
|
if (model_) {
|
||||||
result.model_->WhitenInPlace(result.Ab_.full());
|
result.model_->WhitenInPlace(result.Ab_.full());
|
||||||
result.model_ = SharedDiagonal();
|
result.model_ = SharedDiagonal();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
GaussianFactor::shared_ptr JacobianFactor::negate() const {
|
GaussianFactor::shared_ptr JacobianFactor::negate() const {
|
||||||
HessianFactor hessian(*this);
|
HessianFactor hessian(*this);
|
||||||
return hessian.negate();
|
return hessian.negate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
std::pair<boost::shared_ptr<GaussianConditional>, boost::shared_ptr<JacobianFactor> >
|
std::pair<boost::shared_ptr<GaussianConditional>,
|
||||||
JacobianFactor::eliminate(const Ordering& keys)
|
boost::shared_ptr<JacobianFactor> > JacobianFactor::eliminate(
|
||||||
{
|
const Ordering& keys) {
|
||||||
GaussianFactorGraph graph;
|
GaussianFactorGraph graph;
|
||||||
graph.add(*this);
|
graph.add(*this);
|
||||||
return EliminateQR(graph, keys);
|
return EliminateQR(graph, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void JacobianFactor::setModel(bool anyConstrained, const Vector& sigmas) {
|
void JacobianFactor::setModel(bool anyConstrained, const Vector& sigmas) {
|
||||||
if((size_t) sigmas.size() != this->rows())
|
if ((size_t) sigmas.size() != this->rows())
|
||||||
throw InvalidNoiseModel(this->rows(), sigmas.size());
|
throw InvalidNoiseModel(this->rows(), sigmas.size());
|
||||||
if (anyConstrained)
|
if (anyConstrained)
|
||||||
model_ = noiseModel::Constrained::MixedSigmas(sigmas);
|
model_ = noiseModel::Constrained::MixedSigmas(sigmas);
|
||||||
else
|
else
|
||||||
model_ = noiseModel::Diagonal::Sigmas(sigmas);
|
model_ = noiseModel::Diagonal::Sigmas(sigmas);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
std::pair<boost::shared_ptr<GaussianConditional>, boost::shared_ptr<JacobianFactor> >
|
std::pair<boost::shared_ptr<GaussianConditional>,
|
||||||
EliminateQR(const GaussianFactorGraph& factors, const Ordering& keys)
|
boost::shared_ptr<JacobianFactor> > EliminateQR(
|
||||||
{
|
const GaussianFactorGraph& factors, const Ordering& keys) {
|
||||||
gttic(EliminateQR);
|
gttic(EliminateQR);
|
||||||
// Combine and sort variable blocks in elimination order
|
// Combine and sort variable blocks in elimination order
|
||||||
JacobianFactor::shared_ptr jointFactor;
|
JacobianFactor::shared_ptr jointFactor;
|
||||||
try {
|
try {
|
||||||
jointFactor = boost::make_shared<JacobianFactor>(factors, keys);
|
jointFactor = boost::make_shared<JacobianFactor>(factors, keys);
|
||||||
} catch(std::invalid_argument&) {
|
} catch (std::invalid_argument&) {
|
||||||
throw InvalidDenseElimination(
|
throw InvalidDenseElimination(
|
||||||
"EliminateQR was called with a request to eliminate variables that are not\n"
|
"EliminateQR was called with a request to eliminate variables that are not\n"
|
||||||
"involved in the provided factors.");
|
"involved in the provided factors.");
|
||||||
|
@ -629,7 +654,7 @@ namespace gtsam {
|
||||||
|
|
||||||
// Do dense elimination
|
// Do dense elimination
|
||||||
SharedDiagonal noiseModel;
|
SharedDiagonal noiseModel;
|
||||||
if(jointFactor->model_)
|
if (jointFactor->model_)
|
||||||
jointFactor->model_ = jointFactor->model_->QR(jointFactor->Ab_.matrix());
|
jointFactor->model_ = jointFactor->model_->QR(jointFactor->Ab_.matrix());
|
||||||
else
|
else
|
||||||
inplace_QR(jointFactor->Ab_.matrix());
|
inplace_QR(jointFactor->Ab_.matrix());
|
||||||
|
@ -638,18 +663,20 @@ namespace gtsam {
|
||||||
jointFactor->Ab_.matrix().triangularView<Eigen::StrictlyLower>().setZero();
|
jointFactor->Ab_.matrix().triangularView<Eigen::StrictlyLower>().setZero();
|
||||||
|
|
||||||
// Split elimination result into conditional and remaining factor
|
// Split elimination result into conditional and remaining factor
|
||||||
GaussianConditional::shared_ptr conditional = jointFactor->splitConditional(keys.size());
|
GaussianConditional::shared_ptr conditional = jointFactor->splitConditional(
|
||||||
|
keys.size());
|
||||||
|
|
||||||
return make_pair(conditional, jointFactor);
|
return make_pair(conditional, jointFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
GaussianConditional::shared_ptr JacobianFactor::splitConditional(size_t nrFrontals)
|
GaussianConditional::shared_ptr JacobianFactor::splitConditional(
|
||||||
{
|
size_t nrFrontals) {
|
||||||
gttic(JacobianFactor_splitConditional);
|
gttic(JacobianFactor_splitConditional);
|
||||||
|
|
||||||
if(nrFrontals > size())
|
if (nrFrontals > size())
|
||||||
throw std::invalid_argument("Requesting to split more variables than exist using JacobianFactor::splitConditional");
|
throw std::invalid_argument(
|
||||||
|
"Requesting to split more variables than exist using JacobianFactor::splitConditional");
|
||||||
|
|
||||||
DenseIndex frontalDim = Ab_.range(0, nrFrontals).cols();
|
DenseIndex frontalDim = Ab_.range(0, nrFrontals).cols();
|
||||||
|
|
||||||
|
@ -658,18 +685,20 @@ namespace gtsam {
|
||||||
const DenseIndex originalRowEnd = Ab_.rowEnd();
|
const DenseIndex originalRowEnd = Ab_.rowEnd();
|
||||||
Ab_.rowEnd() = Ab_.rowStart() + frontalDim;
|
Ab_.rowEnd() = Ab_.rowStart() + frontalDim;
|
||||||
SharedDiagonal conditionalNoiseModel;
|
SharedDiagonal conditionalNoiseModel;
|
||||||
if(model_) {
|
if (model_) {
|
||||||
if((DenseIndex)model_->dim() < frontalDim)
|
if ((DenseIndex) model_->dim() < frontalDim)
|
||||||
throw IndeterminantLinearSystemException(this->keys().front());
|
throw IndeterminantLinearSystemException(this->keys().front());
|
||||||
conditionalNoiseModel =
|
conditionalNoiseModel = noiseModel::Diagonal::Sigmas(
|
||||||
noiseModel::Diagonal::Sigmas(model_->sigmas().segment(Ab_.rowStart(), Ab_.rows()));
|
model_->sigmas().segment(Ab_.rowStart(), Ab_.rows()));
|
||||||
}
|
}
|
||||||
GaussianConditional::shared_ptr conditional = boost::make_shared<GaussianConditional>(
|
GaussianConditional::shared_ptr conditional = boost::make_shared<
|
||||||
Base::keys_, nrFrontals, Ab_, conditionalNoiseModel);
|
GaussianConditional>(Base::keys_, nrFrontals, Ab_, conditionalNoiseModel);
|
||||||
const DenseIndex maxRemainingRows = std::min(Ab_.cols() - 1, originalRowEnd) - Ab_.rowStart() - frontalDim;
|
const DenseIndex maxRemainingRows = std::min(Ab_.cols() - 1, originalRowEnd)
|
||||||
|
- Ab_.rowStart() - frontalDim;
|
||||||
const DenseIndex remainingRows =
|
const DenseIndex remainingRows =
|
||||||
model_ ? std::min(model_->sigmas().size() - frontalDim, maxRemainingRows)
|
model_ ?
|
||||||
: maxRemainingRows;
|
std::min(model_->sigmas().size() - frontalDim, maxRemainingRows) :
|
||||||
|
maxRemainingRows;
|
||||||
Ab_.rowStart() += frontalDim;
|
Ab_.rowStart() += frontalDim;
|
||||||
Ab_.rowEnd() = Ab_.rowStart() + remainingRows;
|
Ab_.rowEnd() = Ab_.rowStart() + remainingRows;
|
||||||
Ab_.firstBlock() += nrFrontals;
|
Ab_.firstBlock() += nrFrontals;
|
||||||
|
@ -679,16 +708,18 @@ namespace gtsam {
|
||||||
gttic(remaining_factor);
|
gttic(remaining_factor);
|
||||||
keys_.erase(begin(), begin() + nrFrontals);
|
keys_.erase(begin(), begin() + nrFrontals);
|
||||||
// Set sigmas with the right model
|
// Set sigmas with the right model
|
||||||
if(model_) {
|
if (model_) {
|
||||||
if (model_->isConstrained())
|
if (model_->isConstrained())
|
||||||
model_ = noiseModel::Constrained::MixedSigmas(model_->sigmas().tail(remainingRows));
|
model_ = noiseModel::Constrained::MixedSigmas(
|
||||||
|
model_->sigmas().tail(remainingRows));
|
||||||
else
|
else
|
||||||
model_ = noiseModel::Diagonal::Sigmas(model_->sigmas().tail(remainingRows));
|
model_ = noiseModel::Diagonal::Sigmas(
|
||||||
|
model_->sigmas().tail(remainingRows));
|
||||||
assert(model_->dim() == (size_t)Ab_.rows());
|
assert(model_->dim() == (size_t)Ab_.rows());
|
||||||
}
|
}
|
||||||
gttoc(remaining_factor);
|
gttoc(remaining_factor);
|
||||||
|
|
||||||
return conditional;
|
return conditional;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue