Cleanup with NonlinearConstraints to make the active() function do thresholding for inequality constraints, rather than constraint function itself.
testSQP now has all tests active and passing. Added greaterThanOrEqual() for vector comparison.release/4.3a0
parent
1799f59388
commit
a3ce3f31c8
|
@ -14,10 +14,7 @@ namespace gtsam {
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template <class Config>
|
template <class Config>
|
||||||
bool NonlinearConstraint<Config>::active(const Config& config) const {
|
bool NonlinearConstraint<Config>::active(const Config& config) const {
|
||||||
if (!isEquality_ && zero(error_vector(config)))
|
return !(!isEquality_ && greaterThanOrEqual(error_vector(config), zero(p_)));
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace gtsam {
|
||||||
delta.print("delta");
|
delta.print("delta");
|
||||||
|
|
||||||
// update config
|
// update config
|
||||||
shared_config newConfig(new C(config_->exmap(delta)));
|
shared_config newConfig(new C(config_->exmap(delta))); // TODO: updateConfig
|
||||||
if (verbosity >= TRYCONFIG)
|
if (verbosity >= TRYCONFIG)
|
||||||
newConfig->print("config");
|
newConfig->print("config");
|
||||||
|
|
||||||
|
|
|
@ -38,10 +38,10 @@ namespace gtsam {
|
||||||
LAMBDA,
|
LAMBDA,
|
||||||
CONFIG,
|
CONFIG,
|
||||||
DELTA,
|
DELTA,
|
||||||
LINEAR,
|
|
||||||
TRYLAMBDA,
|
TRYLAMBDA,
|
||||||
TRYCONFIG,
|
TRYCONFIG,
|
||||||
TRYDELTA,
|
TRYDELTA,
|
||||||
|
LINEAR,
|
||||||
DAMPED
|
DAMPED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ SQPOptimizer<G, C> SQPOptimizer<G, C>::iterate(Verbosity v) const {
|
||||||
GaussianFactorGraph fg;
|
GaussianFactorGraph fg;
|
||||||
|
|
||||||
// prepare an ordering of lagrange multipliers to remove
|
// prepare an ordering of lagrange multipliers to remove
|
||||||
Ordering rem;
|
Ordering keysToRemove;
|
||||||
|
|
||||||
// iterate over all factors and linearize
|
// iterate over all factors and linearize
|
||||||
for (const_iterator factor = graph_->begin(); factor < graph_->end(); factor++) {
|
for (const_iterator factor = graph_->begin(); factor < graph_->end(); factor++) {
|
||||||
|
@ -115,22 +115,22 @@ SQPOptimizer<G, C> SQPOptimizer<G, C>::iterate(Verbosity v) const {
|
||||||
fg.push_back(c);
|
fg.push_back(c);
|
||||||
} else {
|
} else {
|
||||||
if (verbose) constraint->print("Skipping...");
|
if (verbose) constraint->print("Skipping...");
|
||||||
rem += constraint->lagrangeKey();
|
keysToRemove += constraint->lagrangeKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verbose) fg.print("Before Optimization");
|
if (verbose) fg.print("Before Optimization");
|
||||||
|
|
||||||
// optimize linear graph to get full delta config
|
// optimize linear graph to get full delta config
|
||||||
VectorConfig delta = fg.optimize(full_ordering_.subtract(rem));
|
VectorConfig delta = fg.optimize(full_ordering_.subtract(keysToRemove));
|
||||||
|
|
||||||
if (verbose) delta.print("Delta Config");
|
if (verbose) delta.print("Delta Config");
|
||||||
|
|
||||||
// update both state variables
|
// update both state variables
|
||||||
shared_config newConfig(new C(config_->exmap(delta)));
|
shared_config newConfig(new C(config_->exmap(delta)));
|
||||||
shared_vconfig newLamConfig(new VectorConfig(lagrange_config_->exmap(delta)));
|
shared_vconfig newLambdas(new VectorConfig(lagrange_config_->exmap(delta)));
|
||||||
|
|
||||||
// construct a new optimizer
|
// construct a new optimizer
|
||||||
return SQPOptimizer<G, C>(*graph_, full_ordering_, newConfig, newLamConfig);
|
return SQPOptimizer<G, C>(*graph_, full_ordering_, newConfig, newLambdas);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **************************************************************** */
|
/* **************************************************************** */
|
||||||
|
|
|
@ -111,6 +111,17 @@ namespace gtsam {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
bool greaterThanOrEqual(const Vector& vec1, const Vector& vec2) {
|
||||||
|
Vector::const_iterator it1 = vec1.begin();
|
||||||
|
Vector::const_iterator it2 = vec2.begin();
|
||||||
|
size_t m = vec1.size();
|
||||||
|
for(size_t i=0; i<m; i++)
|
||||||
|
if(!(it1[i] >= it2[i]))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
bool equal_with_abs_tol(const Vector& vec1, const Vector& vec2, double tol) {
|
bool equal_with_abs_tol(const Vector& vec1, const Vector& vec2, double tol) {
|
||||||
Vector::const_iterator it1 = vec1.begin();
|
Vector::const_iterator it1 = vec1.begin();
|
||||||
|
|
|
@ -87,6 +87,13 @@ void print(const Vector& v, const std::string& s = "");
|
||||||
*/
|
*/
|
||||||
bool operator==(const Vector& vec1,const Vector& vec2);
|
bool operator==(const Vector& vec1,const Vector& vec2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Greater than or equal to operation
|
||||||
|
* returns true if all elements in v1
|
||||||
|
* are greater than corresponding elements in v2
|
||||||
|
*/
|
||||||
|
bool greaterThanOrEqual(const Vector& v1, const Vector& v2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VecA == VecB up to tolerance
|
* VecA == VecB up to tolerance
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -528,25 +528,16 @@ TEST (SQP, stereo_truth ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TEST DISABLED: optimization becomes unstable with one coordinate
|
|
||||||
// growing indefinitely and by the 4th iteration the system is
|
|
||||||
// underconstrained
|
|
||||||
/**
|
/**
|
||||||
* Ground truth for a visual slam example with stereo vision
|
* Ground truth for a visual slam example with stereo vision
|
||||||
* with some noise injected into the initial config
|
* with some noise injected into the initial config
|
||||||
*/
|
*/
|
||||||
TEST (SQP, stereo_truth_noisy ) {
|
TEST (SQP, stereo_truth_noisy ) {
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
int maxIt = 5;
|
|
||||||
|
|
||||||
// setting to determine how far away the noisy landmark is,
|
// setting to determine how far away the noisy landmark is,
|
||||||
// given that the ground truth is 5m in front of the cameras
|
// given that the ground truth is 5m in front of the cameras
|
||||||
double noisyDist = 7.4;
|
double noisyDist = 7.6;
|
||||||
/** RESULTS of optimization based on size of error:
|
|
||||||
* With a ground truth distance away of 5m, results based on initial input:
|
|
||||||
* >= 7.5m: the system diverges
|
|
||||||
* < 7.5m: system finds a solution with near zero error
|
|
||||||
*/
|
|
||||||
|
|
||||||
// create initial estimates
|
// create initial estimates
|
||||||
Rot3 faceDownY(Matrix_(3,3,
|
Rot3 faceDownY(Matrix_(3,3,
|
||||||
|
@ -604,17 +595,9 @@ TEST (SQP, stereo_truth_noisy ) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
cout << "Initial Error: " << optimizer.error() << endl;
|
cout << "Initial Error: " << optimizer.error() << endl;
|
||||||
|
|
||||||
// use Gauss-Newton optimization
|
// use Levenberg-Marquardt optimization
|
||||||
double relThresh = 1e-5, absThresh = 1e-5;
|
double relThresh = 1e-5, absThresh = 1e-5;
|
||||||
optimizer = optimizer.gaussNewton(relThresh, absThresh);
|
optimizer = optimizer.levenbergMarquardt(relThresh, absThresh, VOptimizer::SILENT);
|
||||||
|
|
||||||
// // optimize
|
|
||||||
// for (int i = 0; i<maxIt; ++i) {
|
|
||||||
// cout << "Iteration: " << i << endl;
|
|
||||||
// optimizer = optimizer.iterate();
|
|
||||||
// optimizer.config()->print("Updated Config");
|
|
||||||
// cout << "Error after iteration: " << optimizer.error() << endl;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
DOUBLES_EQUAL(0.0, optimizer.error(), 1e-9);
|
DOUBLES_EQUAL(0.0, optimizer.error(), 1e-9);
|
||||||
|
@ -742,10 +725,6 @@ TEST (SQP, stereo_sqp ) {
|
||||||
CHECK(assert_equal(*truthConfig,*(afterOneIteration.config())));
|
CHECK(assert_equal(*truthConfig,*(afterOneIteration.config())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TEST DISABLED: There is a stability problem that sends the solution
|
|
||||||
// further away with every iteration, and eventually will result in the linearized
|
|
||||||
// system being underconstrained
|
|
||||||
/**
|
/**
|
||||||
* SQP version of the above stereo example,
|
* SQP version of the above stereo example,
|
||||||
* with noise in the initial estimate
|
* with noise in the initial estimate
|
||||||
|
@ -807,12 +786,9 @@ TEST (SQP, stereo_sqp_noisy ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if correct
|
// check if correct
|
||||||
//CHECK(assert_equal(*truthConfig,*(optimizer.config())));
|
CHECK(assert_equal(*truthConfig,*(optimizer.config())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEST DISABLED: There is a stability problem that sends the solution
|
|
||||||
// further away with every iteration, and eventually will result in the linearized
|
|
||||||
// system being underconstrained
|
|
||||||
/**
|
/**
|
||||||
* SQP version of the above stereo example,
|
* SQP version of the above stereo example,
|
||||||
* with noise in the initial estimate and manually specified
|
* with noise in the initial estimate and manually specified
|
||||||
|
@ -855,17 +831,17 @@ TEST (SQP, stereo_sqp_noisy_manualLagrange ) {
|
||||||
// optimize
|
// optimize
|
||||||
double start_error = optimizer.error();
|
double start_error = optimizer.error();
|
||||||
int maxIt = 5;
|
int maxIt = 5;
|
||||||
// for (int i=0; i<maxIt; ++i) {
|
for (int i=0; i<maxIt; ++i) {
|
||||||
// if (verbose) {
|
if (verbose) {
|
||||||
// cout << "\n ************************** \n"
|
cout << "\n ************************** \n"
|
||||||
// << " Iteration: " << i << endl;
|
<< " Iteration: " << i << endl;
|
||||||
// optimizer.config()->print("Config Before Iteration");
|
optimizer.config()->print("Config Before Iteration");
|
||||||
// optimizer.configLagrange()->print("Lagrange Before Iteration");
|
optimizer.configLagrange()->print("Lagrange Before Iteration");
|
||||||
// optimizer = optimizer.iterate(SOptimizer::FULL);
|
optimizer = optimizer.iterate(SOptimizer::FULL);
|
||||||
// }
|
}
|
||||||
// else
|
else
|
||||||
// optimizer = optimizer.iterate(SOptimizer::SILENT);
|
optimizer = optimizer.iterate(SOptimizer::SILENT);
|
||||||
// }
|
}
|
||||||
|
|
||||||
if (verbose) cout << "Initial Error: " << start_error << "\n"
|
if (verbose) cout << "Initial Error: " << start_error << "\n"
|
||||||
<< "Final Error: " << optimizer.error() << endl;
|
<< "Final Error: " << optimizer.error() << endl;
|
||||||
|
@ -880,7 +856,7 @@ TEST (SQP, stereo_sqp_noisy_manualLagrange ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if correct
|
// check if correct
|
||||||
//CHECK(assert_equal(*truthConfig,*(optimizer.config())));
|
CHECK(assert_equal(*truthConfig,*(optimizer.config())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -224,15 +224,12 @@ namespace sqp_avoid1 {
|
||||||
double radius = 1.0;
|
double radius = 1.0;
|
||||||
|
|
||||||
// binary avoidance constraint
|
// binary avoidance constraint
|
||||||
/** g(x) = ||x2-obs||^2 > radius^2 */
|
/** g(x) = ||x2-obs||^2 - radius^2 > 0 */
|
||||||
Vector g_func(const VectorConfig& config, const list<string>& keys) {
|
Vector g_func(const VectorConfig& config, const list<string>& keys) {
|
||||||
Vector delta = config[keys.front()]-config[keys.back()];
|
Vector delta = config[keys.front()]-config[keys.back()];
|
||||||
double dist2 = sum(emul(delta, delta));
|
double dist2 = sum(emul(delta, delta));
|
||||||
double thresh = radius*radius;
|
double thresh = radius*radius;
|
||||||
if (dist2 < thresh)
|
|
||||||
return Vector_(1, dist2-thresh);
|
return Vector_(1, dist2-thresh);
|
||||||
else
|
|
||||||
return zero(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** gradient at pose */
|
/** gradient at pose */
|
||||||
|
|
|
@ -209,6 +209,15 @@ TEST( TestVector, equals )
|
||||||
CHECK(!equal_with_abs_tol(v1, v2, tol));
|
CHECK(!equal_with_abs_tol(v1, v2, tol));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( TestVector, greater_than )
|
||||||
|
{
|
||||||
|
Vector v1 = Vector_(3, 1.0, 2.0, 3.0),
|
||||||
|
v2 = zero(3);
|
||||||
|
CHECK(greaterThanOrEqual(v1, v1)); // test basic greater than
|
||||||
|
CHECK(greaterThanOrEqual(v1, v2)); // test equals
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
|
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
Loading…
Reference in New Issue