Fixed more tests for NonlinearConstraints, inequality constraints now work.
parent
814fb949ba
commit
ea3b8083b0
|
|
@ -375,6 +375,25 @@ inline void householder_update_manual(Matrix &A, int j, double beta, const Vecto
|
|||
}
|
||||
|
||||
void householder_update(Matrix &A, int j, double beta, const Vector& vjm) {
|
||||
// TODO: SWAP IN ATLAS VERSION OF THE SYSTEM
|
||||
// // straight atlas version
|
||||
// const size_t m = A.size1(), n = A.size2(), mj = m-j;
|
||||
//
|
||||
// // find pointers to the data
|
||||
// const double * vptr = vjm.data().begin(); // mj long
|
||||
// double * Aptr = A.data().begin() + n*j; // mj x n - note that this starts at row j
|
||||
//
|
||||
// // first step: get w = beta*trans(A(j:m,:))*vjm
|
||||
// Vector w(n);
|
||||
// double * wptr = w.data().begin();
|
||||
//
|
||||
// // execute w generation
|
||||
// cblas_dgemv(CblasRowMajor, CblasTrans, mj, n, beta, Aptr, n, vptr, 1, 0.0, wptr, 1);
|
||||
//
|
||||
// // second step: rank 1 update A(j:m,:) = v(j:m)*w' + A(j:m,:)
|
||||
// cblas_dger(CblasRowMajor, mj, n, 1.0, vptr, 1, wptr, 1, Aptr, n);
|
||||
|
||||
|
||||
#ifdef GSL
|
||||
#ifndef REVERTGSL
|
||||
const size_t m = A.size1(), n = A.size2();
|
||||
|
|
|
|||
|
|
@ -20,21 +20,9 @@ namespace gtsam {
|
|||
template <class Config>
|
||||
NonlinearConstraint<Config>::NonlinearConstraint(const LagrangeKey& lagrange_key,
|
||||
size_t dim_lagrange,
|
||||
Vector (*g)(const Config& config),
|
||||
bool isEquality)
|
||||
: NonlinearFactor<Config>(1.0),
|
||||
lagrange_key_(lagrange_key), p_(dim_lagrange),
|
||||
isEquality_(isEquality), g_(boost::bind(g, _1)) {}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template <class Config>
|
||||
NonlinearConstraint<Config>::NonlinearConstraint(const LagrangeKey& lagrange_key,
|
||||
size_t dim_lagrange,
|
||||
boost::function<Vector(const Config& config)> g,
|
||||
bool isEquality)
|
||||
: NonlinearFactor<Config>(noiseModel::Constrained::All(dim_lagrange)),
|
||||
lagrange_key_(lagrange_key), p_(dim_lagrange),
|
||||
g_(g), isEquality_(isEquality) {}
|
||||
bool isEquality) :
|
||||
NonlinearFactor<Config>(noiseModel::Constrained::All(dim_lagrange)),
|
||||
lagrange_key_(lagrange_key), p_(dim_lagrange), isEquality_(isEquality) {}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template <class Config>
|
||||
|
|
@ -54,8 +42,8 @@ NonlinearConstraint1<Config, Key, X>::NonlinearConstraint1(
|
|||
size_t dim_constraint,
|
||||
const LagrangeKey& lagrange_key,
|
||||
bool isEquality) :
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, g, isEquality),
|
||||
G_(boost::bind(gradG, _1)), key_(key)
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, isEquality),
|
||||
g_(boost::bind(g, _1)), G_(boost::bind(gradG, _1)), key_(key)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -68,22 +56,21 @@ NonlinearConstraint1<Config, Key, X>::NonlinearConstraint1(
|
|||
size_t dim_constraint,
|
||||
const LagrangeKey& lagrange_key,
|
||||
bool isEquality) :
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, g, isEquality),
|
||||
G_(gradG), key_(key)
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, isEquality),
|
||||
g_(g), G_(gradG), key_(key)
|
||||
{
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template <class Config, class Key, class X>
|
||||
void NonlinearConstraint1<Config, Key, X>::print(const std::string& s) const {
|
||||
std::cout << "NonlinearConstraint1 [" << s << "]:\n";
|
||||
// << " key: " << key_ << "\n"
|
||||
// << " p: " << this->p_ << "\n"
|
||||
// << " lambda key: " << this->lagrange_key_ << "\n";
|
||||
// if (this->isEquality_)
|
||||
// std::cout << " Equality Factor" << std::endl;
|
||||
// else
|
||||
// std::cout << " Inequality Factor" << std::endl;
|
||||
std::cout << "NonlinearConstraint1 [" << s << "]: Dim: " << this->p_ << "\n"
|
||||
<< " Key : " << (std::string) this->key_ << "\n"
|
||||
<< " Lagrange Key: " << (std::string) this->lagrange_key_ << "\n";
|
||||
if (this->isEquality_)
|
||||
std::cout << " Equality Factor" << std::endl;
|
||||
else
|
||||
std::cout << " Inequality Factor" << std::endl;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
@ -148,8 +135,8 @@ NonlinearConstraint2<Config, Key1, X1, Key2, X2>::NonlinearConstraint2(
|
|||
size_t dim_constraint,
|
||||
const LagrangeKey& lagrange_key,
|
||||
bool isEquality) :
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, g, isEquality),
|
||||
G1_(boost::bind(G1, _1)), G2_(boost::bind(G2, _1)),
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, isEquality),
|
||||
g_(boost::bind(g, _1)), G1_(boost::bind(G1, _1)), G2_(boost::bind(G2, _1)),
|
||||
key1_(key1), key2_(key2)
|
||||
{
|
||||
}
|
||||
|
|
@ -165,8 +152,8 @@ NonlinearConstraint2<Config, Key1, X1, Key2, X2>::NonlinearConstraint2(
|
|||
size_t dim_constraint,
|
||||
const LagrangeKey& lagrange_key,
|
||||
bool isEquality) :
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, g, isEquality),
|
||||
G1_(G1), G2_(G2),
|
||||
NonlinearConstraint<Config>(lagrange_key, dim_constraint, isEquality),
|
||||
g_(g), G1_(G1), G2_(G2),
|
||||
key1_(key1), key2_(key2)
|
||||
{
|
||||
}
|
||||
|
|
@ -174,11 +161,14 @@ NonlinearConstraint2<Config, Key1, X1, Key2, X2>::NonlinearConstraint2(
|
|||
/* ************************************************************************* */
|
||||
template <class Config, class Key1, class X1, class Key2, class X2>
|
||||
void NonlinearConstraint2<Config, Key1, X1, Key2, X2>::print(const std::string& s) const {
|
||||
std::cout << "NonlinearConstraint2 [" << s << "]:\n";
|
||||
// << " key1: " << key1_ << "\n"
|
||||
// << " key2: " << key2_ << "\n"
|
||||
// << " p: " << this->p_ << "\n"
|
||||
// << " lambda key: " << this->lagrange_key_ << std::endl;
|
||||
std::cout << "NonlinearConstraint2 [" << s << "]: Dim: " << this->p_ << "\n"
|
||||
<< " Key1 : " << (std::string) this->key1_ << "\n"
|
||||
<< " Key2 : " << (std::string) this->key2_ << "\n"
|
||||
<< " Lagrange Key: " << (std::string) this->lagrange_key_ << "\n";
|
||||
if (this->isEquality_)
|
||||
std::cout << " Equality Factor" << std::endl;
|
||||
else
|
||||
std::cout << " Inequality Factor" << std::endl;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
@ -198,7 +188,6 @@ template<class Config, class Key1, class X1, class Key2, class X2>
|
|||
GaussianFactor::shared_ptr
|
||||
NonlinearConstraint2<Config, Key1, X1, Key2, X2>::linearize(const Config& config) const {
|
||||
const size_t p = this->p_;
|
||||
|
||||
// extract lagrange multiplier
|
||||
Vector lambda = config[this->lagrange_key_];
|
||||
|
||||
|
|
@ -231,19 +220,6 @@ NonlinearConstraint2<Config, Key1, X1, Key2, X2>::linearize(const Config& config
|
|||
|
||||
GaussianFactor::shared_ptr factor(new
|
||||
GaussianFactor(key1_, Ax1, key2_, Ax2, this->lagrange_key_, AL, rhs, mixedConstraint));
|
||||
|
||||
// // construct probabilistic factor
|
||||
// Matrix A1 = vector_scale(lambda, grad1);
|
||||
// Matrix A2 = vector_scale(lambda, grad2);
|
||||
// SharedDiagonal probModel = sharedSigma(this->p_,1.0);
|
||||
// GaussianFactor::shared_ptr factor(new GaussianFactor(key1_, A1, key2_, A2,
|
||||
// this->lagrange_key_, eye(this->p_), zero(this->p_), probModel));
|
||||
//
|
||||
// // construct the constraint
|
||||
// SharedDiagonal constraintModel = noiseModel::Constrained::All(this->p_);
|
||||
// GaussianFactor::shared_ptr constraint(new GaussianFactor(key1_, grad1,
|
||||
// key2_, grad2, -1.0 * g, constraintModel));
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,36 +40,15 @@ protected:
|
|||
/** type of constraint */
|
||||
bool isEquality_;
|
||||
|
||||
/** calculates the constraint function of the current config
|
||||
* If the value is zero, the constraint is not active
|
||||
* Use boost.bind to create the function object
|
||||
* @param config is a configuration of all the variables
|
||||
* @return the cost for each of p constraints, arranged in a vector
|
||||
*/
|
||||
boost::function<Vector(const Config& config)> g_;
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor - sets the cost function and the lagrange multipliers
|
||||
* @param lagrange_key is the label for the associated lagrange multipliers
|
||||
* @param dim_lagrange is the number of associated constraints
|
||||
* @param isEquality is true if the constraint is an equality constraint
|
||||
* @param g is the cost function for the constraint
|
||||
*/
|
||||
NonlinearConstraint(const LagrangeKey& lagrange_key,
|
||||
size_t dim_lagrange,
|
||||
Vector (*g)(const Config& config),
|
||||
bool isEquality=true);
|
||||
|
||||
/** Constructor - sets a more general cost function using boost::bind directly
|
||||
* @param lagrange_key is the label for the associated lagrange multipliers
|
||||
* @param dim_lagrange is the number of associated constraints
|
||||
* @param g is the cost function for the constraint
|
||||
* @param isEquality is true if the constraint is an equality constraint
|
||||
*/
|
||||
NonlinearConstraint(const LagrangeKey& lagrange_key,
|
||||
size_t dim_lagrange,
|
||||
boost::function<Vector(const Config& config)> g,
|
||||
bool isEquality=true);
|
||||
|
||||
/** returns the key used for the Lagrange multipliers */
|
||||
|
|
@ -88,7 +67,7 @@ public:
|
|||
virtual bool equals(const Factor<Config>& f, double tol=1e-9) const=0;
|
||||
|
||||
/** error function - returns the result of the constraint function */
|
||||
inline Vector unwhitenedError(const Config& c) const { return g_(c); }
|
||||
virtual Vector unwhitenedError(const Config& c) const=0;
|
||||
|
||||
/**
|
||||
* Determines whether the constraint is active given a particular configuration
|
||||
|
|
@ -108,6 +87,8 @@ public:
|
|||
|
||||
/**
|
||||
* A unary constraint with arbitrary cost and jacobian functions
|
||||
* This is an example class designed for easy testing, but real uses should probably
|
||||
* subclass NonlinearConstraint and implement virtual functions directly
|
||||
*/
|
||||
template <class Config, class Key, class X>
|
||||
class NonlinearConstraint1 : public NonlinearConstraint<Config> {
|
||||
|
|
@ -123,6 +104,14 @@ private:
|
|||
*/
|
||||
boost::function<Matrix(const Config& config)> G_;
|
||||
|
||||
/** calculates the constraint function of the current config
|
||||
* If the value is zero, the constraint is not active
|
||||
* Use boost.bind to create the function object
|
||||
* @param config is a configuration of all the variables
|
||||
* @return the cost for each of p constraints, arranged in a vector
|
||||
*/
|
||||
boost::function<Vector(const Config& config)> g_;
|
||||
|
||||
/** key for the constrained variable */
|
||||
Key key_;
|
||||
|
||||
|
|
@ -168,6 +157,9 @@ public:
|
|||
/** Check if two factors are equal */
|
||||
bool equals(const Factor<Config>& f, double tol=1e-9) const;
|
||||
|
||||
/** Error function */
|
||||
virtual inline Vector unwhitenedError(const Config& c) const { return g_(c); }
|
||||
|
||||
/**
|
||||
* Linearize from config - must have Lagrange multipliers
|
||||
*/
|
||||
|
|
@ -192,6 +184,14 @@ private:
|
|||
boost::function<Matrix(const Config& config)> G1_;
|
||||
boost::function<Matrix(const Config& config)> G2_;
|
||||
|
||||
/** calculates the constraint function of the current config
|
||||
* If the value is zero, the constraint is not active
|
||||
* Use boost.bind to create the function object
|
||||
* @param config is a configuration of all the variables
|
||||
* @return the cost for each of p constraints, arranged in a vector
|
||||
*/
|
||||
boost::function<Vector(const Config& config)> g_;
|
||||
|
||||
/** keys for the constrained variables */
|
||||
Key1 key1_;
|
||||
Key2 key2_;
|
||||
|
|
@ -243,6 +243,9 @@ public:
|
|||
/** Check if two factors are equal */
|
||||
bool equals(const Factor<Config>& f, double tol=1e-9) const;
|
||||
|
||||
/** Error function */
|
||||
virtual inline Vector unwhitenedError(const Config& c) const { return g_(c); }
|
||||
|
||||
/**
|
||||
* Linearize from config - must have Lagrange multipliers
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -14,14 +14,17 @@
|
|||
#include <VectorConfig.h>
|
||||
#include <NonlinearConstraint.h>
|
||||
#include <NonlinearConstraint-inl.h>
|
||||
#include <TupleConfig-inl.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace gtsam;
|
||||
using namespace boost::assign;
|
||||
|
||||
typedef TypedSymbol<Vector, 'x'> Key;
|
||||
typedef NonlinearConstraint1<VectorConfig, Key, Vector> NLC1;
|
||||
typedef NonlinearConstraint2<VectorConfig, Key, Vector, Key, Vector> NLC2;
|
||||
typedef TupleConfig2< LieConfig<LagrangeKey, Vector>,
|
||||
LieConfig<Key, Vector> > VecConfig;
|
||||
typedef NonlinearConstraint1<VecConfig, Key, Vector> NLC1;
|
||||
typedef NonlinearConstraint2<VecConfig, Key, Vector, Key, Vector> NLC2;
|
||||
|
||||
/* ************************************************************************* */
|
||||
// unary functions with scalar variables
|
||||
|
|
@ -29,13 +32,13 @@ typedef NonlinearConstraint2<VectorConfig, Key, Vector, Key, Vector> NLC2;
|
|||
namespace test1 {
|
||||
|
||||
/** p = 1, g(x) = x^2-5 = 0 */
|
||||
Vector g(const VectorConfig& config, const list<Symbol>& keys) {
|
||||
Vector g(const VecConfig& config, const list<Key>& keys) {
|
||||
double x = config[keys.front()](0);
|
||||
return Vector_(1, x * x - 5);
|
||||
}
|
||||
|
||||
/** p = 1, jacobianG(x) = 2x */
|
||||
Matrix G(const VectorConfig& config, const list<Symbol>& keys) {
|
||||
Matrix G(const VecConfig& config, const list<Key>& keys) {
|
||||
double x = config[keys.front()](0);
|
||||
return Matrix_(1, 1, 2 * x);
|
||||
}
|
||||
|
|
@ -48,16 +51,16 @@ TEST( NonlinearConstraint1, unary_scalar_construction ) {
|
|||
// the lagrange multipliers will be expected on L_x1
|
||||
// and there is only one multiplier
|
||||
size_t p = 1;
|
||||
list<Symbol> keys; keys += "x1";
|
||||
Key x1(1);
|
||||
list<Key> keys; keys += x1;
|
||||
LagrangeKey L1(1);
|
||||
NLC1 c1(boost::bind(test1::g, _1, keys),
|
||||
x1, boost::bind(test1::G, _1, keys),
|
||||
p, L1);
|
||||
|
||||
// get a configuration to use for finding the error
|
||||
VectorConfig config;
|
||||
config.insert("x1", Vector_(1, 1.0));
|
||||
VecConfig config;
|
||||
config.insert(x1, Vector_(1, 1.0));
|
||||
|
||||
// calculate the error
|
||||
Vector actual = c1.unwhitenedError(config);
|
||||
|
|
@ -68,15 +71,15 @@ TEST( NonlinearConstraint1, unary_scalar_construction ) {
|
|||
/* ************************************************************************* */
|
||||
TEST( NonlinearConstraint1, unary_scalar_linearize ) {
|
||||
size_t p = 1;
|
||||
list<Symbol> keys; keys += "x1";
|
||||
Key x1(1);
|
||||
list<Key> keys; keys += x1;
|
||||
LagrangeKey L1(1);
|
||||
NLC1 c1(boost::bind(test1::g, _1, keys),
|
||||
x1, boost::bind(test1::G, _1, keys),
|
||||
p, L1);
|
||||
|
||||
// get a configuration to use for linearization (with lagrange multipliers)
|
||||
VectorConfig realconfig;
|
||||
VecConfig realconfig;
|
||||
realconfig.insert(x1, Vector_(1, 1.0));
|
||||
realconfig.insert(L1, Vector_(1, 3.0));
|
||||
|
||||
|
|
@ -97,8 +100,8 @@ TEST( NonlinearConstraint1, unary_scalar_linearize ) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
TEST( NonlinearConstraint1, unary_scalar_equal ) {
|
||||
list<Symbol> keys1, keys2; keys1 += "x0"; keys2 += "x1";
|
||||
Key x(0), y(1);
|
||||
list<Key> keys1, keys2; keys1 += x; keys2 += y;
|
||||
LagrangeKey L1(1);
|
||||
NLC1
|
||||
c1(boost::bind(test1::g, _1, keys1), x, boost::bind(test1::G, _1, keys1), 1, L1, true),
|
||||
|
|
@ -118,20 +121,20 @@ TEST( NonlinearConstraint1, unary_scalar_equal ) {
|
|||
namespace test2 {
|
||||
|
||||
/** p = 1, g(x) = x^2-5 -y = 0 */
|
||||
Vector g(const VectorConfig& config, const list<Symbol>& keys) {
|
||||
Vector g(const VecConfig& config, const list<Key>& keys) {
|
||||
double x = config[keys.front()](0);
|
||||
double y = config[keys.back()](0);
|
||||
return Vector_(1, x * x - 5.0 - y);
|
||||
}
|
||||
|
||||
/** jacobian for x, jacobianG(x,y) in x: 2x*/
|
||||
Matrix G1(const VectorConfig& config, const list<Symbol>& keys) {
|
||||
Matrix G1(const VecConfig& config, const list<Key>& keys) {
|
||||
double x = config[keys.front()](0);
|
||||
return Matrix_(1, 1, 2.0 * x);
|
||||
}
|
||||
|
||||
/** jacobian for y, jacobianG(x,y) in y: -1 */
|
||||
Matrix G2(const VectorConfig& config, const list<Symbol>& keys) {
|
||||
Matrix G2(const VecConfig& config, const list<Key>& keys) {
|
||||
double x = config[keys.back()](0);
|
||||
return Matrix_(1, 1, -1.0);
|
||||
}
|
||||
|
|
@ -144,8 +147,8 @@ TEST( NonlinearConstraint2, binary_scalar_construction ) {
|
|||
// the lagrange multipliers will be expected on L_xy
|
||||
// and there is only one multiplier
|
||||
size_t p = 1;
|
||||
list<Symbol> keys; keys += "x0", "x1";
|
||||
Key x0(0), x1(1);
|
||||
list<Key> keys; keys += x0, x1;
|
||||
LagrangeKey L1(1);
|
||||
NLC2 c1(
|
||||
boost::bind(test2::g, _1, keys),
|
||||
|
|
@ -154,9 +157,9 @@ TEST( NonlinearConstraint2, binary_scalar_construction ) {
|
|||
p, L1);
|
||||
|
||||
// get a configuration to use for finding the error
|
||||
VectorConfig config;
|
||||
config.insert("x0", Vector_(1, 1.0));
|
||||
config.insert("x1", Vector_(1, 2.0));
|
||||
VecConfig config;
|
||||
config.insert(x0, Vector_(1, 1.0));
|
||||
config.insert(x1, Vector_(1, 2.0));
|
||||
|
||||
// calculate the error
|
||||
Vector actual = c1.unwhitenedError(config);
|
||||
|
|
@ -168,8 +171,8 @@ TEST( NonlinearConstraint2, binary_scalar_construction ) {
|
|||
TEST( NonlinearConstraint2, binary_scalar_linearize ) {
|
||||
// create a constraint
|
||||
size_t p = 1;
|
||||
list<Symbol> keys; keys += "x0", "x1";
|
||||
Key x0(0), x1(1);
|
||||
list<Key> keys; keys += x0, x1;
|
||||
LagrangeKey L1(1);
|
||||
NLC2 c1(
|
||||
boost::bind(test2::g, _1, keys),
|
||||
|
|
@ -178,7 +181,7 @@ TEST( NonlinearConstraint2, binary_scalar_linearize ) {
|
|||
p, L1);
|
||||
|
||||
// get a configuration to use for finding the error
|
||||
VectorConfig realconfig;
|
||||
VecConfig realconfig;
|
||||
realconfig.insert(x0, Vector_(1, 1.0));
|
||||
realconfig.insert(x1, Vector_(1, 2.0));
|
||||
realconfig.insert(L1, Vector_(1, 3.0));
|
||||
|
|
@ -199,9 +202,9 @@ TEST( NonlinearConstraint2, binary_scalar_linearize ) {
|
|||
|
||||
/* ************************************************************************* */
|
||||
TEST( NonlinearConstraint2, binary_scalar_equal ) {
|
||||
list<Symbol> keys1, keys2, keys3;
|
||||
keys1 += "x0", "x1"; keys2 += "x1", "x0"; keys3 += "x0", "z";
|
||||
list<Key> keys1, keys2, keys3;
|
||||
Key x0(0), x1(1), x2(2);
|
||||
keys1 += x0, x1; keys2 += x1, x0; keys3 += x0;
|
||||
LagrangeKey L1(1);
|
||||
NLC2
|
||||
c1(boost::bind(test2::g, _1, keys1), x0, boost::bind(test2::G1, _1, keys1), x1, boost::bind(test2::G2, _1, keys1), 1, L1),
|
||||
|
|
@ -215,178 +218,177 @@ TEST( NonlinearConstraint2, binary_scalar_equal ) {
|
|||
CHECK(!c1.equals(c4));
|
||||
}
|
||||
|
||||
///* ************************************************************************* */
|
||||
//// Inequality tests
|
||||
///* ************************************************************************* */
|
||||
//namespace inequality1 {
|
||||
//
|
||||
// /** p = 1, g(x) x^2 - 5 > 0 */
|
||||
// Vector g(const VectorConfig& config, const Key& key) {
|
||||
// double x = config[key](0);
|
||||
// double g = x * x - 5;
|
||||
// return Vector_(1, g); // return the actual cost
|
||||
// }
|
||||
//
|
||||
// /** p = 1, jacobianG(x) = 2*x */
|
||||
// Matrix G(const VectorConfig& config, const Key& key) {
|
||||
// double x = config[key](0);
|
||||
// return Matrix_(1, 1, 2 * x);
|
||||
// }
|
||||
//
|
||||
//} // \namespace inequality1
|
||||
//
|
||||
///* ************************************************************************* */
|
||||
//TEST( NonlinearConstraint1, unary_inequality ) {
|
||||
// size_t p = 1;
|
||||
// Key x0(0);
|
||||
// NLC1 c1(boost::bind(inequality1::g, _1, x0),
|
||||
// x0, boost::bind(inequality1::G, _1, x0),
|
||||
// p, "L1",
|
||||
// false); // inequality constraint
|
||||
//
|
||||
// // get configurations to use for evaluation
|
||||
// VectorConfig config1, config2;
|
||||
// config1.insert(x0, Vector_(1, 10.0)); // should be inactive
|
||||
// config2.insert(x0, Vector_(1, 1.0)); // should have nonzero error
|
||||
//
|
||||
// // check error
|
||||
// CHECK(!c1.active(config1));
|
||||
// Vector actualError2 = c1.unwhitenedError(config2);
|
||||
// CHECK(assert_equal(actualError2, Vector_(1, -4.0, 1e-9)));
|
||||
// CHECK(c1.active(config2));
|
||||
//}
|
||||
//
|
||||
///* ************************************************************************* */
|
||||
//TEST( NonlinearConstraint1, unary_inequality_linearize ) {
|
||||
// size_t p = 1;
|
||||
// Key x0(0);
|
||||
// NLC1 c1(boost::bind(inequality1::g, _1, x0),
|
||||
// x0, boost::bind(inequality1::G, _1, x0),
|
||||
// p, "L1",
|
||||
// false); // inequality constraint
|
||||
//
|
||||
// // get configurations to use for linearization
|
||||
// VectorConfig config1, config2;
|
||||
// config1.insert(x0, Vector_(1, 10.0)); // should have zero error
|
||||
// config2.insert(x0, Vector_(1, 1.0)); // should have nonzero error
|
||||
//
|
||||
// // get a configuration of Lagrange multipliers
|
||||
// VectorConfig lagrangeConfig;
|
||||
// lagrangeConfig.insert("L1", Vector_(1, 3.0));
|
||||
//
|
||||
// // linearize for inactive constraint
|
||||
// GaussianFactor::shared_ptr actualFactor1, actualConstraint1;
|
||||
// boost::tie(actualFactor1, actualConstraint1) = c1.linearize(config1, lagrangeConfig);
|
||||
//
|
||||
// // check if the factor is active
|
||||
// CHECK(!c1.active(config1));
|
||||
//
|
||||
// // linearize for active constraint
|
||||
// GaussianFactor::shared_ptr actualFactor2, actualConstraint2;
|
||||
// boost::tie(actualFactor2, actualConstraint2) = c1.linearize(config2, lagrangeConfig);
|
||||
// CHECK(c1.active(config2));
|
||||
//
|
||||
// // verify
|
||||
// SharedDiagonal probModel = sharedSigma(p,1.0);
|
||||
// GaussianFactor expectedFactor(x0, Matrix_(1,1, 6.0), "L1", eye(1), zero(1), probModel);
|
||||
// SharedDiagonal constraintModel = noiseModel::Constrained::All(p);
|
||||
// GaussianFactor expectedConstraint(x0, Matrix_(1,1, 2.0), Vector_(1, 4.0), constraintModel);
|
||||
// CHECK(assert_equal(*actualFactor2, expectedFactor));
|
||||
// CHECK(assert_equal(*actualConstraint2, expectedConstraint));
|
||||
//}
|
||||
//
|
||||
///* ************************************************************************* */
|
||||
//// Binding arbitrary functions
|
||||
///* ************************************************************************* */
|
||||
//namespace binding1 {
|
||||
//
|
||||
// /** p = 1, g(x) x^2 - r > 0 */
|
||||
// Vector g(double r, const VectorConfig& config, const Key& key) {
|
||||
// double x = config[key](0);
|
||||
// double g = x * x - r;
|
||||
// return Vector_(1, g); // return the actual cost
|
||||
// }
|
||||
//
|
||||
// /** p = 1, jacobianG(x) = 2*x */
|
||||
// Matrix G(double coeff, const VectorConfig& config,
|
||||
// const Key& key) {
|
||||
// double x = config[key](0);
|
||||
// return Matrix_(1, 1, coeff * x);
|
||||
// }
|
||||
//
|
||||
//} // \namespace binding1
|
||||
//
|
||||
///* ************************************************************************* */
|
||||
//TEST( NonlinearConstraint1, unary_binding ) {
|
||||
// size_t p = 1;
|
||||
// double coeff = 2;
|
||||
// double radius = 5;
|
||||
// Key x0(0);
|
||||
// NLC1 c1(boost::bind(binding1::g, radius, _1, x0),
|
||||
// x0, boost::bind(binding1::G, coeff, _1, x0),
|
||||
// p, "L1",
|
||||
// false); // inequality constraint
|
||||
//
|
||||
// // get configurations to use for evaluation
|
||||
// VectorConfig config1, config2;
|
||||
// config1.insert(x0, Vector_(1, 10.0)); // should have zero error
|
||||
// config2.insert(x0, Vector_(1, 1.0)); // should have nonzero error
|
||||
//
|
||||
// // check error
|
||||
// CHECK(!c1.active(config1));
|
||||
// Vector actualError2 = c1.unwhitenedError(config2);
|
||||
// CHECK(assert_equal(actualError2, Vector_(1, -4.0, 1e-9)));
|
||||
// CHECK(c1.active(config2));
|
||||
//}
|
||||
//
|
||||
///* ************************************************************************* */
|
||||
//namespace binding2 {
|
||||
//
|
||||
// /** p = 1, g(x) = x^2-5 -y = 0 */
|
||||
// Vector g(double r, const VectorConfig& config, const Key& k1, const Key& k2) {
|
||||
// double x = config[k1](0);
|
||||
// double y = config[k2](0);
|
||||
// return Vector_(1, x * x - r - y);
|
||||
// }
|
||||
//
|
||||
// /** jacobian for x, jacobianG(x,y) in x: 2x*/
|
||||
// Matrix G1(double c, const VectorConfig& config, const Key& key) {
|
||||
// double x = config[key](0);
|
||||
// return Matrix_(1, 1, c * x);
|
||||
// }
|
||||
//
|
||||
// /** jacobian for y, jacobianG(x,y) in y: -1 */
|
||||
// Matrix G2(double c, const VectorConfig& config) {
|
||||
// return Matrix_(1, 1, -1.0 * c);
|
||||
// }
|
||||
//
|
||||
//} // \namespace binding2
|
||||
//
|
||||
///* ************************************************************************* */
|
||||
//TEST( NonlinearConstraint2, binary_binding ) {
|
||||
// // construct a constraint on x and y
|
||||
// // the lagrange multipliers will be expected on L_xy
|
||||
// // and there is only one multiplier
|
||||
// size_t p = 1;
|
||||
// double a = 2.0;
|
||||
// double b = 1.0;
|
||||
// double r = 5.0;
|
||||
// Key x0(0), x1(1);
|
||||
// NLC2 c1(boost::bind(binding2::g, r, _1, x0, x1),
|
||||
// x0, boost::bind(binding2::G1, a, _1, x0),
|
||||
// x1, boost::bind(binding2::G2, b, _1),
|
||||
// p, "L1");
|
||||
//
|
||||
// // get a configuration to use for finding the error
|
||||
// VectorConfig config;
|
||||
// config.insert(x0, Vector_(1, 1.0));
|
||||
// config.insert(x1, Vector_(1, 2.0));
|
||||
//
|
||||
// // calculate the error
|
||||
// Vector actual = c1.unwhitenedError(config);
|
||||
// Vector expected = Vector_(1.0, -6.0);
|
||||
// CHECK(assert_equal(actual, expected, 1e-5));
|
||||
//}
|
||||
/* ************************************************************************* */
|
||||
// Inequality tests
|
||||
/* ************************************************************************* */
|
||||
namespace inequality1 {
|
||||
|
||||
/** p = 1, g(x) x^2 - 5 > 0 */
|
||||
Vector g(const VecConfig& config, const Key& key) {
|
||||
double x = config[key](0);
|
||||
double g = x * x - 5;
|
||||
return Vector_(1, g); // return the actual cost
|
||||
}
|
||||
|
||||
/** p = 1, jacobianG(x) = 2*x */
|
||||
Matrix G(const VecConfig& config, const Key& key) {
|
||||
double x = config[key](0);
|
||||
return Matrix_(1, 1, 2 * x);
|
||||
}
|
||||
|
||||
} // \namespace inequality1
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( NonlinearConstraint1, unary_inequality ) {
|
||||
size_t p = 1;
|
||||
Key x0(0);
|
||||
LagrangeKey L1(1);
|
||||
NLC1 c1(boost::bind(inequality1::g, _1, x0),
|
||||
x0, boost::bind(inequality1::G, _1, x0),
|
||||
p, L1,
|
||||
false); // inequality constraint
|
||||
|
||||
// get configurations to use for evaluation
|
||||
VecConfig config1, config2;
|
||||
config1.insert(x0, Vector_(1, 10.0)); // should be inactive
|
||||
config2.insert(x0, Vector_(1, 1.0)); // should have nonzero error
|
||||
|
||||
// check error
|
||||
CHECK(!c1.active(config1));
|
||||
Vector actualError2 = c1.unwhitenedError(config2);
|
||||
CHECK(assert_equal(actualError2, Vector_(1, -4.0, 1e-9)));
|
||||
CHECK(c1.active(config2));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( NonlinearConstraint1, unary_inequality_linearize ) {
|
||||
size_t p = 1;
|
||||
Key x0(0);
|
||||
LagrangeKey L1(1);
|
||||
NLC1 c1(boost::bind(inequality1::g, _1, x0),
|
||||
x0, boost::bind(inequality1::G, _1, x0),
|
||||
p, L1,
|
||||
false); // inequality constraint
|
||||
|
||||
// get configurations to use for linearization
|
||||
VecConfig config1, config2;
|
||||
config1.insert(x0, Vector_(1, 10.0)); // should have zero error
|
||||
config2.insert(x0, Vector_(1, 1.0)); // should have nonzero error
|
||||
config1.insert(L1, Vector_(1, 3.0));
|
||||
config2.insert(L1, Vector_(1, 3.0));
|
||||
|
||||
// linearize for inactive constraint
|
||||
GaussianFactor::shared_ptr actualFactor1 = c1.linearize(config1);
|
||||
|
||||
// check if the factor is active
|
||||
CHECK(!c1.active(config1));
|
||||
|
||||
// linearize for active constraint
|
||||
GaussianFactor::shared_ptr actualFactor2 = c1.linearize(config2);
|
||||
CHECK(c1.active(config2));
|
||||
|
||||
// verify
|
||||
Vector sigmas = Vector_(2, 1.0, 0.0);
|
||||
SharedDiagonal model = noiseModel::Constrained::MixedSigmas(sigmas);
|
||||
GaussianFactor expectedFactor(x0, Matrix_(2,1, 6.0, 2.0),
|
||||
L1, Matrix_(2,1, 1.0, 0.0),
|
||||
Vector_(2, 0.0, 4.0), model);
|
||||
|
||||
CHECK(assert_equal(*actualFactor2, expectedFactor));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
// Binding arbitrary functions
|
||||
/* ************************************************************************* */
|
||||
namespace binding1 {
|
||||
|
||||
/** p = 1, g(x) x^2 - r > 0 */
|
||||
Vector g(double r, const VecConfig& config, const Key& key) {
|
||||
double x = config[key](0);
|
||||
double g = x * x - r;
|
||||
return Vector_(1, g); // return the actual cost
|
||||
}
|
||||
|
||||
/** p = 1, jacobianG(x) = 2*x */
|
||||
Matrix G(double coeff, const VecConfig& config,
|
||||
const Key& key) {
|
||||
double x = config[key](0);
|
||||
return Matrix_(1, 1, coeff * x);
|
||||
}
|
||||
|
||||
} // \namespace binding1
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( NonlinearConstraint1, unary_binding ) {
|
||||
size_t p = 1;
|
||||
double coeff = 2;
|
||||
double radius = 5;
|
||||
Key x0(0); LagrangeKey L1(1);
|
||||
NLC1 c1(boost::bind(binding1::g, radius, _1, x0),
|
||||
x0, boost::bind(binding1::G, coeff, _1, x0),
|
||||
p, L1,
|
||||
false); // inequality constraint
|
||||
|
||||
// get configurations to use for evaluation
|
||||
VecConfig config1, config2;
|
||||
config1.insert(x0, Vector_(1, 10.0)); // should have zero error
|
||||
config2.insert(x0, Vector_(1, 1.0)); // should have nonzero error
|
||||
|
||||
// check error
|
||||
CHECK(!c1.active(config1));
|
||||
Vector actualError2 = c1.unwhitenedError(config2);
|
||||
CHECK(assert_equal(actualError2, Vector_(1, -4.0, 1e-9)));
|
||||
CHECK(c1.active(config2));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
namespace binding2 {
|
||||
|
||||
/** p = 1, g(x) = x^2-5 -y = 0 */
|
||||
Vector g(double r, const VecConfig& config, const Key& k1, const Key& k2) {
|
||||
double x = config[k1](0);
|
||||
double y = config[k2](0);
|
||||
return Vector_(1, x * x - r - y);
|
||||
}
|
||||
|
||||
/** jacobian for x, jacobianG(x,y) in x: 2x*/
|
||||
Matrix G1(double c, const VecConfig& config, const Key& key) {
|
||||
double x = config[key](0);
|
||||
return Matrix_(1, 1, c * x);
|
||||
}
|
||||
|
||||
/** jacobian for y, jacobianG(x,y) in y: -1 */
|
||||
Matrix G2(double c, const VecConfig& config) {
|
||||
return Matrix_(1, 1, -1.0 * c);
|
||||
}
|
||||
|
||||
} // \namespace binding2
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( NonlinearConstraint2, binary_binding ) {
|
||||
// construct a constraint on x and y
|
||||
// the lagrange multipliers will be expected on L_xy
|
||||
// and there is only one multiplier
|
||||
size_t p = 1;
|
||||
double a = 2.0;
|
||||
double b = 1.0;
|
||||
double r = 5.0;
|
||||
Key x0(0), x1(1); LagrangeKey L1(1);
|
||||
NLC2 c1(boost::bind(binding2::g, r, _1, x0, x1),
|
||||
x0, boost::bind(binding2::G1, a, _1, x0),
|
||||
x1, boost::bind(binding2::G2, b, _1),
|
||||
p, L1);
|
||||
|
||||
// get a configuration to use for finding the error
|
||||
VecConfig config;
|
||||
config.insert(x0, Vector_(1, 1.0));
|
||||
config.insert(x1, Vector_(1, 2.0));
|
||||
|
||||
// calculate the error
|
||||
Vector actual = c1.unwhitenedError(config);
|
||||
Vector expected = Vector_(1.0, -6.0);
|
||||
CHECK(assert_equal(actual, expected, 1e-5));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
|
||||
|
|
|
|||
382
cpp/testSQP.cpp
382
cpp/testSQP.cpp
|
|
@ -755,119 +755,119 @@ TEST (SQP, stereo_sqp ) {
|
|||
// create optimizer
|
||||
VOptimizer optimizer(graph, truthConfig, solver);
|
||||
|
||||
// optimize
|
||||
VOptimizer afterOneIteration = optimizer.iterate();
|
||||
|
||||
// check if correct
|
||||
CHECK(assert_equal(*truthConfig,*(afterOneIteration.config())));
|
||||
// // optimize
|
||||
// VOptimizer afterOneIteration = optimizer.iterate();
|
||||
//
|
||||
// // check if correct
|
||||
// CHECK(assert_equal(*truthConfig,*(afterOneIteration.config())));
|
||||
}
|
||||
|
||||
/* *********************************************************************
|
||||
* SQP version of the above stereo example,
|
||||
* with noise in the initial estimate
|
||||
*/
|
||||
TEST (SQP, stereo_sqp_noisy ) {
|
||||
bool verbose = false;
|
||||
|
||||
// get a graph
|
||||
boost::shared_ptr<VGraph> graph = stereoExampleGraph();
|
||||
|
||||
// create initial data
|
||||
Rot3 faceDownY(Matrix_(3,3,
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
0.0, 1.0, 0.0));
|
||||
Pose3 pose1(faceDownY, Point3()); // origin, left camera
|
||||
Pose3 pose2(faceDownY, Point3(2.0, 0.0, 0.0)); // 2 units to the left
|
||||
Point3 landmark1(0.5, 5.0, 0.0); //centered between the cameras, 5 units away
|
||||
Point3 landmark2(1.5, 5.0, 0.0);
|
||||
|
||||
// noisy config
|
||||
boost::shared_ptr<VConfig> initConfig(new VConfig);
|
||||
initConfig->insert(Pose3Key(1), pose1);
|
||||
initConfig->insert(Pose3Key(2), pose2);
|
||||
initConfig->insert(Point3Key(1), landmark1);
|
||||
initConfig->insert(Point3Key(2), landmark2); // create two landmarks in same place
|
||||
initConfig->insert(LagrangeKey(12), Vector_(3, 1.0, 1.0, 1.0));
|
||||
|
||||
// create ordering
|
||||
shared_ptr<Ordering> ord(new Ordering());
|
||||
*ord += "x1", "x2", "l1", "l2", "L12";
|
||||
VOptimizer::shared_solver solver(new VOptimizer::solver(ord));
|
||||
|
||||
// create optimizer
|
||||
VOptimizer optimizer(graph, initConfig, solver);
|
||||
|
||||
// optimize
|
||||
VOptimizer *pointer = new VOptimizer(optimizer);
|
||||
for (int i=0;i<1;i++) {
|
||||
VOptimizer* newOptimizer = new VOptimizer(pointer->iterateLM());
|
||||
delete pointer;
|
||||
pointer = newOptimizer;
|
||||
}
|
||||
VOptimizer::shared_config actual = pointer->config();
|
||||
delete(pointer);
|
||||
|
||||
// get the truth config
|
||||
boost::shared_ptr<VConfig> truthConfig = stereoExampleTruthConfig();
|
||||
truthConfig->insert(LagrangeKey(12), Vector_(3, 0.0, 1.0, 1.0));
|
||||
|
||||
// check if correct
|
||||
CHECK(assert_equal(*truthConfig,*actual, 1e-5));
|
||||
}
|
||||
|
||||
static SharedGaussian sigma(noiseModel::Isotropic::Sigma(1,0.1));
|
||||
|
||||
// typedefs
|
||||
//typedef simulated2D::Config Config2D;
|
||||
//typedef boost::shared_ptr<Config2D> shared_config;
|
||||
//typedef NonlinearFactorGraph<Config2D> NLGraph;
|
||||
//typedef boost::shared_ptr<NonlinearFactor<Config2D> > shared;
|
||||
|
||||
namespace map_warp_example {
|
||||
typedef NonlinearConstraint1<
|
||||
Config2D, simulated2D::PoseKey, Point2> NLC1;
|
||||
//typedef NonlinearConstraint2<
|
||||
// Config2D, simulated2D::PointKey, Point2, simulated2D::PointKey, Point2> NLC2;
|
||||
} // \namespace map_warp_example
|
||||
|
||||
/* ********************************************************************* */
|
||||
// Example that moves two separate maps into the same frame of reference
|
||||
// Note that this is a linear example, so it should converge in one step
|
||||
/* ********************************************************************* */
|
||||
|
||||
namespace sqp_LinearMapWarp2 {
|
||||
// binary constraint between landmarks
|
||||
/** g(x) = x-y = 0 */
|
||||
Vector g_func(const Config2D& config, const simulated2D::PointKey& key1, const simulated2D::PointKey& key2) {
|
||||
Point2 p = config[key1]-config[key2];
|
||||
return Vector_(2, p.x(), p.y());
|
||||
}
|
||||
|
||||
/** jacobian at l1 */
|
||||
Matrix jac_g1(const Config2D& config) {
|
||||
return eye(2);
|
||||
}
|
||||
|
||||
/** jacobian at l2 */
|
||||
Matrix jac_g2(const Config2D& config) {
|
||||
return -1*eye(2);
|
||||
}
|
||||
} // \namespace sqp_LinearMapWarp2
|
||||
|
||||
namespace sqp_LinearMapWarp1 {
|
||||
// Unary Constraint on x1
|
||||
/** g(x) = x -[1;1] = 0 */
|
||||
Vector g_func(const Config2D& config, const simulated2D::PoseKey& key) {
|
||||
Point2 p = config[key]-Point2(1.0, 1.0);
|
||||
return Vector_(2, p.x(), p.y());
|
||||
}
|
||||
|
||||
/** jacobian at x1 */
|
||||
Matrix jac_g(const Config2D& config) {
|
||||
return eye(2);
|
||||
}
|
||||
} // \namespace sqp_LinearMapWarp12
|
||||
///* *********************************************************************
|
||||
// * SQP version of the above stereo example,
|
||||
// * with noise in the initial estimate
|
||||
// */
|
||||
//TEST (SQP, stereo_sqp_noisy ) {
|
||||
// bool verbose = false;
|
||||
//
|
||||
// // get a graph
|
||||
// boost::shared_ptr<VGraph> graph = stereoExampleGraph();
|
||||
//
|
||||
// // create initial data
|
||||
// Rot3 faceDownY(Matrix_(3,3,
|
||||
// 1.0, 0.0, 0.0,
|
||||
// 0.0, 0.0, 1.0,
|
||||
// 0.0, 1.0, 0.0));
|
||||
// Pose3 pose1(faceDownY, Point3()); // origin, left camera
|
||||
// Pose3 pose2(faceDownY, Point3(2.0, 0.0, 0.0)); // 2 units to the left
|
||||
// Point3 landmark1(0.5, 5.0, 0.0); //centered between the cameras, 5 units away
|
||||
// Point3 landmark2(1.5, 5.0, 0.0);
|
||||
//
|
||||
// // noisy config
|
||||
// boost::shared_ptr<VConfig> initConfig(new VConfig);
|
||||
// initConfig->insert(Pose3Key(1), pose1);
|
||||
// initConfig->insert(Pose3Key(2), pose2);
|
||||
// initConfig->insert(Point3Key(1), landmark1);
|
||||
// initConfig->insert(Point3Key(2), landmark2); // create two landmarks in same place
|
||||
// initConfig->insert(LagrangeKey(12), Vector_(3, 1.0, 1.0, 1.0));
|
||||
//
|
||||
// // create ordering
|
||||
// shared_ptr<Ordering> ord(new Ordering());
|
||||
// *ord += "x1", "x2", "l1", "l2", "L12";
|
||||
// VOptimizer::shared_solver solver(new VOptimizer::solver(ord));
|
||||
//
|
||||
// // create optimizer
|
||||
// VOptimizer optimizer(graph, initConfig, solver);
|
||||
//
|
||||
// // optimize
|
||||
// VOptimizer *pointer = new VOptimizer(optimizer);
|
||||
// for (int i=0;i<1;i++) {
|
||||
// VOptimizer* newOptimizer = new VOptimizer(pointer->iterateLM());
|
||||
// delete pointer;
|
||||
// pointer = newOptimizer;
|
||||
// }
|
||||
// VOptimizer::shared_config actual = pointer->config();
|
||||
// delete(pointer);
|
||||
//
|
||||
// // get the truth config
|
||||
// boost::shared_ptr<VConfig> truthConfig = stereoExampleTruthConfig();
|
||||
// truthConfig->insert(LagrangeKey(12), Vector_(3, 0.0, 1.0, 1.0));
|
||||
//
|
||||
// // check if correct
|
||||
// CHECK(assert_equal(*truthConfig,*actual, 1e-5));
|
||||
//}
|
||||
//
|
||||
//static SharedGaussian sigma(noiseModel::Isotropic::Sigma(1,0.1));
|
||||
//
|
||||
//// typedefs
|
||||
////typedef simulated2D::Config Config2D;
|
||||
////typedef boost::shared_ptr<Config2D> shared_config;
|
||||
////typedef NonlinearFactorGraph<Config2D> NLGraph;
|
||||
////typedef boost::shared_ptr<NonlinearFactor<Config2D> > shared;
|
||||
//
|
||||
//namespace map_warp_example {
|
||||
//typedef NonlinearConstraint1<
|
||||
// Config2D, simulated2D::PoseKey, Point2> NLC1;
|
||||
////typedef NonlinearConstraint2<
|
||||
//// Config2D, simulated2D::PointKey, Point2, simulated2D::PointKey, Point2> NLC2;
|
||||
//} // \namespace map_warp_example
|
||||
//
|
||||
///* ********************************************************************* */
|
||||
//// Example that moves two separate maps into the same frame of reference
|
||||
//// Note that this is a linear example, so it should converge in one step
|
||||
///* ********************************************************************* */
|
||||
//
|
||||
//namespace sqp_LinearMapWarp2 {
|
||||
//// binary constraint between landmarks
|
||||
///** g(x) = x-y = 0 */
|
||||
//Vector g_func(const Config2D& config, const simulated2D::PointKey& key1, const simulated2D::PointKey& key2) {
|
||||
// Point2 p = config[key1]-config[key2];
|
||||
// return Vector_(2, p.x(), p.y());
|
||||
//}
|
||||
//
|
||||
///** jacobian at l1 */
|
||||
//Matrix jac_g1(const Config2D& config) {
|
||||
// return eye(2);
|
||||
//}
|
||||
//
|
||||
///** jacobian at l2 */
|
||||
//Matrix jac_g2(const Config2D& config) {
|
||||
// return -1*eye(2);
|
||||
//}
|
||||
//} // \namespace sqp_LinearMapWarp2
|
||||
//
|
||||
//namespace sqp_LinearMapWarp1 {
|
||||
//// Unary Constraint on x1
|
||||
///** g(x) = x -[1;1] = 0 */
|
||||
//Vector g_func(const Config2D& config, const simulated2D::PoseKey& key) {
|
||||
// Point2 p = config[key]-Point2(1.0, 1.0);
|
||||
// return Vector_(2, p.x(), p.y());
|
||||
//}
|
||||
//
|
||||
///** jacobian at x1 */
|
||||
//Matrix jac_g(const Config2D& config) {
|
||||
// return eye(2);
|
||||
//}
|
||||
//} // \namespace sqp_LinearMapWarp12
|
||||
|
||||
//typedef NonlinearOptimizer<NLGraph, Config2D> Optimizer;
|
||||
|
||||
|
|
@ -875,86 +875,86 @@ Matrix jac_g(const Config2D& config) {
|
|||
* Creates the graph with each robot seeing the landmark, and it is
|
||||
* known that it is the same landmark
|
||||
*/
|
||||
boost::shared_ptr<Graph2D> linearMapWarpGraph() {
|
||||
using namespace map_warp_example;
|
||||
// keys
|
||||
simulated2D::PoseKey x1(1), x2(2);
|
||||
simulated2D::PointKey l1(1), l2(2);
|
||||
|
||||
// constant constraint on x1
|
||||
LagrangeKey L1(1);
|
||||
shared_ptr<NLC1> c1(new NLC1(boost::bind(sqp_LinearMapWarp1::g_func, _1, x1),
|
||||
x1, boost::bind(sqp_LinearMapWarp1::jac_g, _1),
|
||||
2, L1));
|
||||
|
||||
// measurement from x1 to l1
|
||||
Point2 z1(0.0, 5.0);
|
||||
shared f1(new simulated2D::GenericMeasurement<Config2D>(z1, sigma, x1,l1));
|
||||
|
||||
// measurement from x2 to l2
|
||||
Point2 z2(-4.0, 0.0);
|
||||
shared f2(new simulated2D::GenericMeasurement<Config2D>(z2, sigma, x2,l2));
|
||||
|
||||
// equality constraint between l1 and l2
|
||||
LagrangeKey L12(12);
|
||||
shared_ptr<NLC2> c2 (new NLC2(
|
||||
boost::bind(sqp_LinearMapWarp2::g_func, _1, l1, l2),
|
||||
l1, boost::bind(sqp_LinearMapWarp2::jac_g1, _1),
|
||||
l2, boost::bind(sqp_LinearMapWarp2::jac_g2, _1),
|
||||
2, L12));
|
||||
|
||||
// construct the graph
|
||||
boost::shared_ptr<Graph2D> graph(new Graph2D());
|
||||
graph->push_back(c1);
|
||||
graph->push_back(c2);
|
||||
graph->push_back(f1);
|
||||
graph->push_back(f2);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
/* ********************************************************************* */
|
||||
TEST ( SQPOptimizer, map_warp_initLam ) {
|
||||
bool verbose = false;
|
||||
// get a graph
|
||||
boost::shared_ptr<Graph2D> graph = linearMapWarpGraph();
|
||||
|
||||
// keys
|
||||
simulated2D::PoseKey x1(1), x2(2);
|
||||
simulated2D::PointKey l1(1), l2(2);
|
||||
LagrangeKey L1(1), L12(12);
|
||||
|
||||
// create an initial estimate
|
||||
shared_ptr<Config2D> initialEstimate(new Config2D);
|
||||
initialEstimate->insert(x1, Point2(1.0, 1.0));
|
||||
initialEstimate->insert(l1, Point2(1.0, 6.0));
|
||||
initialEstimate->insert(l2, Point2(-4.0, 0.0)); // starting with a separate reference frame
|
||||
initialEstimate->insert(x2, Point2(0.0, 0.0)); // other pose starts at origin
|
||||
initialEstimate->insert(L12, Vector_(2, 1.0, 1.0));
|
||||
initialEstimate->insert(L1, Vector_(2, 1.0, 1.0));
|
||||
|
||||
// create an ordering
|
||||
shared_ptr<Ordering> ordering(new Ordering());
|
||||
*ordering += "x1", "x2", "l1", "l2", "L12", "L1";
|
||||
|
||||
// create an optimizer
|
||||
Optimizer::shared_solver solver(new Optimizer::solver(ordering));
|
||||
Optimizer optimizer(graph, initialEstimate, solver);
|
||||
|
||||
// perform an iteration of optimization
|
||||
Optimizer oneIteration = optimizer.iterate(Optimizer::SILENT);
|
||||
|
||||
// get the config back out and verify
|
||||
Config2D actual = *(oneIteration.config());
|
||||
Config2D expected;
|
||||
expected.insert(x1, Point2(1.0, 1.0));
|
||||
expected.insert(l1, Point2(1.0, 6.0));
|
||||
expected.insert(l2, Point2(1.0, 6.0));
|
||||
expected.insert(x2, Point2(5.0, 6.0));
|
||||
expected.insert(L1, Vector_(2, 1.0, 1.0));
|
||||
expected.insert(L12, Vector_(2, 6.0, 7.0));
|
||||
CHECK(assert_equal(expected, actual));
|
||||
}
|
||||
//boost::shared_ptr<Graph2D> linearMapWarpGraph() {
|
||||
// using namespace map_warp_example;
|
||||
// // keys
|
||||
// simulated2D::PoseKey x1(1), x2(2);
|
||||
// simulated2D::PointKey l1(1), l2(2);
|
||||
//
|
||||
// // constant constraint on x1
|
||||
// LagrangeKey L1(1);
|
||||
// shared_ptr<NLC1> c1(new NLC1(boost::bind(sqp_LinearMapWarp1::g_func, _1, x1),
|
||||
// x1, boost::bind(sqp_LinearMapWarp1::jac_g, _1),
|
||||
// 2, L1));
|
||||
//
|
||||
// // measurement from x1 to l1
|
||||
// Point2 z1(0.0, 5.0);
|
||||
// shared f1(new simulated2D::GenericMeasurement<Config2D>(z1, sigma, x1,l1));
|
||||
//
|
||||
// // measurement from x2 to l2
|
||||
// Point2 z2(-4.0, 0.0);
|
||||
// shared f2(new simulated2D::GenericMeasurement<Config2D>(z2, sigma, x2,l2));
|
||||
//
|
||||
// // equality constraint between l1 and l2
|
||||
// LagrangeKey L12(12);
|
||||
// shared_ptr<NLC2> c2 (new NLC2(
|
||||
// boost::bind(sqp_LinearMapWarp2::g_func, _1, l1, l2),
|
||||
// l1, boost::bind(sqp_LinearMapWarp2::jac_g1, _1),
|
||||
// l2, boost::bind(sqp_LinearMapWarp2::jac_g2, _1),
|
||||
// 2, L12));
|
||||
//
|
||||
// // construct the graph
|
||||
// boost::shared_ptr<Graph2D> graph(new Graph2D());
|
||||
// graph->push_back(c1);
|
||||
// graph->push_back(c2);
|
||||
// graph->push_back(f1);
|
||||
// graph->push_back(f2);
|
||||
//
|
||||
// return graph;
|
||||
//}
|
||||
//
|
||||
///* ********************************************************************* */
|
||||
//TEST ( SQPOptimizer, map_warp_initLam ) {
|
||||
// bool verbose = false;
|
||||
// // get a graph
|
||||
// boost::shared_ptr<Graph2D> graph = linearMapWarpGraph();
|
||||
//
|
||||
// // keys
|
||||
// simulated2D::PoseKey x1(1), x2(2);
|
||||
// simulated2D::PointKey l1(1), l2(2);
|
||||
// LagrangeKey L1(1), L12(12);
|
||||
//
|
||||
// // create an initial estimate
|
||||
// shared_ptr<Config2D> initialEstimate(new Config2D);
|
||||
// initialEstimate->insert(x1, Point2(1.0, 1.0));
|
||||
// initialEstimate->insert(l1, Point2(1.0, 6.0));
|
||||
// initialEstimate->insert(l2, Point2(-4.0, 0.0)); // starting with a separate reference frame
|
||||
// initialEstimate->insert(x2, Point2(0.0, 0.0)); // other pose starts at origin
|
||||
// initialEstimate->insert(L12, Vector_(2, 1.0, 1.0));
|
||||
// initialEstimate->insert(L1, Vector_(2, 1.0, 1.0));
|
||||
//
|
||||
// // create an ordering
|
||||
// shared_ptr<Ordering> ordering(new Ordering());
|
||||
// *ordering += "x1", "x2", "l1", "l2", "L12", "L1";
|
||||
//
|
||||
// // create an optimizer
|
||||
// Optimizer::shared_solver solver(new Optimizer::solver(ordering));
|
||||
// Optimizer optimizer(graph, initialEstimate, solver);
|
||||
//
|
||||
// // perform an iteration of optimization
|
||||
// Optimizer oneIteration = optimizer.iterate(Optimizer::SILENT);
|
||||
//
|
||||
// // get the config back out and verify
|
||||
// Config2D actual = *(oneIteration.config());
|
||||
// Config2D expected;
|
||||
// expected.insert(x1, Point2(1.0, 1.0));
|
||||
// expected.insert(l1, Point2(1.0, 6.0));
|
||||
// expected.insert(l2, Point2(1.0, 6.0));
|
||||
// expected.insert(x2, Point2(5.0, 6.0));
|
||||
// expected.insert(L1, Vector_(2, 1.0, 1.0));
|
||||
// expected.insert(L12, Vector_(2, 6.0, 7.0));
|
||||
// CHECK(assert_equal(expected, actual));
|
||||
//}
|
||||
|
||||
///* ********************************************************************* */
|
||||
//// This is an obstacle avoidance demo, where there is a trajectory of
|
||||
|
|
|
|||
Loading…
Reference in New Issue