Added test with pose and a line equality constraint. Works but hessian is incorrect. So basically using nonlinearequality vs linearequality makes no difference.
parent
29e6e67de7
commit
ecc87bdb2b
|
@ -203,6 +203,10 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
#include <gtsam/slam/PriorFactor.h>
|
||||
#include <gtsam/geometry/Pose3.h>
|
||||
#include <gtsam/base/numericalDerivative.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace gtsam::symbol_shorthand;
|
||||
using namespace gtsam;
|
||||
|
@ -226,7 +230,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
TEST_DISABLED(testSQPSimple, QPProblem) {
|
||||
TEST(testSQPSimple, QPProblem) {
|
||||
const Key dualKey = 0;
|
||||
|
||||
// Simple quadratic cost: x1^2 + x2^2
|
||||
|
@ -255,7 +259,10 @@ TEST_DISABLED(testSQPSimple, QPProblem) {
|
|||
|
||||
//Instantiate NLP
|
||||
NLP nlp;
|
||||
nlp.cost.add(LinearContainerFactor(hf)); // wrap it using linearcontainerfactor
|
||||
Values linPoint;
|
||||
linPoint.insert<Vector1>(X(1), zero(1));
|
||||
linPoint.insert<Vector1>(Y(1), zero(1));
|
||||
nlp.cost.add(LinearContainerFactor(hf, linPoint)); // wrap it using linearcontainerfactor
|
||||
nlp.linearEqualities.add(ConstraintProblem1(X(1), Y(1), dualKey));
|
||||
|
||||
Values initialValues;
|
||||
|
@ -301,7 +308,7 @@ TEST_UNSAFE(testSQPSimple, quadraticCostNonlinearConstraint) {
|
|||
//Instantiate NLP
|
||||
NLP nlp;
|
||||
|
||||
// Simple quadratic cost: x1^2 + x2^2
|
||||
// Simple quadratic cost: x1^2 + x2^2 +1000
|
||||
// Note the Hessian encodes:
|
||||
// 0.5*x1'*G11*x1 + x1'*G12*x2 + 0.5*x2'*G22*x2 - x1'*g1 - x2'*g2 + 0.5*f
|
||||
// Hence here we have G11 = 2, G12 = 0, G22 = 2, g1 = 0, g2 = 0, f = 0
|
||||
|
@ -309,13 +316,13 @@ TEST_UNSAFE(testSQPSimple, quadraticCostNonlinearConstraint) {
|
|||
linPoint.insert<Vector1>(X(1), zero(1));
|
||||
linPoint.insert<Vector1>(Y(1), zero(1));
|
||||
HessianFactor hf(X(1), Y(1), 2.0 * ones(1,1), zero(1), zero(1),
|
||||
2*ones(1,1), zero(1) , 0);
|
||||
2*ones(1,1), zero(1) , 1000);
|
||||
nlp.cost.add(LinearContainerFactor(hf, linPoint)); // wrap it using linearcontainerfactor
|
||||
nlp.nonlinearEqualities.add(CircleConstraint(X(1), Y(1), dualKey));
|
||||
|
||||
Values initialValues;
|
||||
initialValues.insert<double>(X(1), 0.0);
|
||||
initialValues.insert<double>(Y(1), 2.0);
|
||||
initialValues.insert<double>(X(1), 4.0);
|
||||
initialValues.insert<double>(Y(1), 10.0);
|
||||
|
||||
Values expectedSolution;
|
||||
expectedSolution.insert<double>(X(1), 0.5);
|
||||
|
@ -330,30 +337,48 @@ TEST_UNSAFE(testSQPSimple, quadraticCostNonlinearConstraint) {
|
|||
}
|
||||
|
||||
//******************************************************************************
|
||||
//
|
||||
//TEST_UNSAFE(testSQPSimple, poseOnALine) {
|
||||
// const Key dualKey = 0;
|
||||
//
|
||||
// //Instantiate NLP
|
||||
// NLP nlp;
|
||||
// nlp.cost.add(PriorFactor<Pose3>(X(1), Pose3(), noiseModel::Unit::Create(6))); // wrap it using linearcontainerfactor
|
||||
// nlp.nonlinearEqualities.add(CircleConstraint(X(1), Y(1), dualKey));
|
||||
//
|
||||
// Values initialValues;
|
||||
// initialValues.insert<double>(X(1), 0.0);
|
||||
// initialValues.insert<double>(Y(1), 0.0);
|
||||
//
|
||||
// Values expectedSolution;
|
||||
// expectedSolution.insert<double>(X(1), 0.5);
|
||||
// expectedSolution.insert<double>(Y(1), 0.0);
|
||||
//
|
||||
// // Instantiate SQP
|
||||
// SQPSimple sqpSimple(nlp);
|
||||
// Values actualSolution = sqpSimple.optimize(initialValues).first;
|
||||
//
|
||||
// CHECK(assert_equal(expectedSolution, actualSolution, 1e-10));
|
||||
// actualSolution.print("actualSolution: ");
|
||||
//}
|
||||
class LineConstraintX : public NonlinearConstraint1<Pose3> {
|
||||
typedef NonlinearConstraint1<Pose3> Base;
|
||||
public:
|
||||
LineConstraintX(Key key, Key dualKey) : Base(key, dualKey, 1) {
|
||||
}
|
||||
|
||||
double computeError(const Pose3& pose) const {
|
||||
return pose.x();
|
||||
}
|
||||
|
||||
Vector evaluateError(const Pose3& pose, boost::optional<Matrix&> H = boost::none) const {
|
||||
if (H)
|
||||
*H = (Matrix(1,6) << zeros(1,3), pose.rotation().matrix().row(0)).finished();
|
||||
return (Vector(1) << pose.x()).finished();
|
||||
}
|
||||
};
|
||||
TEST_UNSAFE(testSQPSimple, poseOnALine) {
|
||||
const Key dualKey = 0;
|
||||
|
||||
|
||||
//Instantiate NLP
|
||||
NLP nlp;
|
||||
nlp.cost.add(PriorFactor<Pose3>(X(1), Pose3(Rot3::ypr(0.1, 0.2, 0.3), Point3(1, 0, 0)), noiseModel::Unit::Create(6)));
|
||||
LineConstraintX constraint(X(1), dualKey);
|
||||
nlp.nonlinearEqualities.add(constraint);
|
||||
|
||||
Values initialValues;
|
||||
initialValues.insert(X(1), Pose3(Rot3::ypr(0.3, 0.2, 0.3), Point3(1,0,0)));
|
||||
|
||||
Values expectedSolution;
|
||||
expectedSolution.insert(X(1), Pose3(Rot3::ypr(0.1, 0.2, 0.3), Point3()));
|
||||
|
||||
// Instantiate SQP
|
||||
SQPSimple sqpSimple(nlp);
|
||||
Values actualSolution = sqpSimple.optimize(initialValues).first;
|
||||
|
||||
CHECK(assert_equal(expectedSolution, actualSolution, 1e-10));
|
||||
actualSolution.print("actualSolution: ");
|
||||
Pose3 pose(Rot3::ypr(0.1, 0.2, 0.3), Point3());
|
||||
Matrix hessian = numericalHessian<Pose3>(boost::bind(&LineConstraintX::computeError, constraint, _1), pose, 1e-2);
|
||||
cout << "hessian: \n" << hessian << endl;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
int main() {
|
||||
|
|
Loading…
Reference in New Issue