user can now also set the weights to initialize gnc!
parent
5274abafd0
commit
d6a3171e67
|
@ -99,6 +99,10 @@ class GncOptimizer {
|
||||||
"that are not in the factor graph to be known outliers.");
|
"that are not in the factor graph to be known outliers.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// initialize weights (if we don't have prior knowledge of inliers/outliers
|
||||||
|
// the weights are all initialized to 1.
|
||||||
|
weights_ = initializeWeightsFromKnownInliersAndOutliers();
|
||||||
|
|
||||||
// set default barcSq_ (inlier threshold)
|
// set default barcSq_ (inlier threshold)
|
||||||
double alpha = 0.99; // with this (default) probability, inlier residuals are smaller than barcSq_
|
double alpha = 0.99; // with this (default) probability, inlier residuals are smaller than barcSq_
|
||||||
setInlierCostThresholdsAtProbability(alpha);
|
setInlierCostThresholdsAtProbability(alpha);
|
||||||
|
@ -134,6 +138,17 @@ class GncOptimizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set weights for each factor. This is typically not needed, but
|
||||||
|
* provides an extra interface for the user to initialize the weightst
|
||||||
|
* */
|
||||||
|
void setWeights(const Vector w) {
|
||||||
|
if(w.size() != nfg_.size()){
|
||||||
|
throw std::runtime_error("GncOptimizer::setWeights: the number of specified weights"
|
||||||
|
" does not match the size of the factor graph.");
|
||||||
|
}
|
||||||
|
weights_ = w;
|
||||||
|
}
|
||||||
|
|
||||||
/// Access a copy of the internal factor graph.
|
/// Access a copy of the internal factor graph.
|
||||||
const NonlinearFactorGraph& getFactors() const { return nfg_; }
|
const NonlinearFactorGraph& getFactors() const { return nfg_; }
|
||||||
|
|
||||||
|
@ -167,8 +182,6 @@ class GncOptimizer {
|
||||||
|
|
||||||
/// Compute optimal solution using graduated non-convexity.
|
/// Compute optimal solution using graduated non-convexity.
|
||||||
Values optimize() {
|
Values optimize() {
|
||||||
// start by assuming all measurements are inliers
|
|
||||||
weights_ = initializeWeightsFromKnownInliersAndOutliers();
|
|
||||||
NonlinearFactorGraph graph_initial = this->makeWeightedGraph(weights_);
|
NonlinearFactorGraph graph_initial = this->makeWeightedGraph(weights_);
|
||||||
BaseOptimizer baseOptimizer(graph_initial, state_);
|
BaseOptimizer baseOptimizer(graph_initial, state_);
|
||||||
Values result = baseOptimizer.optimize();
|
Values result = baseOptimizer.optimize();
|
||||||
|
|
|
@ -660,7 +660,7 @@ TEST(GncOptimizer, barcsq_heterogeneousFactors) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(GncOptimizer, setWeights) {
|
TEST(GncOptimizer, setInlierCostThresholds) {
|
||||||
auto fg = example::sharedNonRobustFactorGraphWithOutliers();
|
auto fg = example::sharedNonRobustFactorGraphWithOutliers();
|
||||||
|
|
||||||
Point2 p0(1, 0);
|
Point2 p0(1, 0);
|
||||||
|
@ -839,6 +839,87 @@ TEST(GncOptimizer, knownInliersAndOutliers) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(GncOptimizer, setWeights) {
|
||||||
|
auto fg = example::sharedNonRobustFactorGraphWithOutliers();
|
||||||
|
|
||||||
|
Point2 p0(1, 0);
|
||||||
|
Values initial;
|
||||||
|
initial.insert(X(1), p0);
|
||||||
|
// initialize weights to be the same
|
||||||
|
{
|
||||||
|
GncParams<GaussNewtonParams> gncParams;
|
||||||
|
gncParams.setLossType(GncLossType::TLS);
|
||||||
|
|
||||||
|
Vector weights = 0.5 * Vector::Ones(fg.size());
|
||||||
|
auto gnc = GncOptimizer<GncParams<GaussNewtonParams>>(fg, initial,
|
||||||
|
gncParams);
|
||||||
|
gnc.setWeights(weights);
|
||||||
|
gnc.setInlierCostThresholds(1.0);
|
||||||
|
Values gnc_result = gnc.optimize();
|
||||||
|
CHECK(assert_equal(Point2(0.0, 0.0), gnc_result.at<Point2>(X(1)), 1e-3));
|
||||||
|
|
||||||
|
// check weights were actually fixed:
|
||||||
|
Vector finalWeights = gnc.getWeights();
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[0], tol);
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[1], tol);
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[2], tol);
|
||||||
|
DOUBLES_EQUAL(0.0, finalWeights[3], tol);
|
||||||
|
}
|
||||||
|
// try a more challenging initialization
|
||||||
|
{
|
||||||
|
GncParams<GaussNewtonParams> gncParams;
|
||||||
|
gncParams.setLossType(GncLossType::TLS);
|
||||||
|
|
||||||
|
Vector weights = Vector::Zero(fg.size());
|
||||||
|
weights(2) = 1.0;
|
||||||
|
weights(3) = 1.0; // bad initialization: we say the outlier is inlier
|
||||||
|
// GNC can still recover (but if you omit weights(2) = 1.0, then it would fail)
|
||||||
|
auto gnc = GncOptimizer<GncParams<GaussNewtonParams>>(fg, initial,
|
||||||
|
gncParams);
|
||||||
|
gnc.setWeights(weights);
|
||||||
|
gnc.setInlierCostThresholds(1.0);
|
||||||
|
Values gnc_result = gnc.optimize();
|
||||||
|
CHECK(assert_equal(Point2(0.0, 0.0), gnc_result.at<Point2>(X(1)), 1e-3));
|
||||||
|
|
||||||
|
// check weights were actually fixed:
|
||||||
|
Vector finalWeights = gnc.getWeights();
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[0], tol);
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[1], tol);
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[2], tol);
|
||||||
|
DOUBLES_EQUAL(0.0, finalWeights[3], tol);
|
||||||
|
}
|
||||||
|
// initialize weights and also set known inliers/outliers
|
||||||
|
{
|
||||||
|
GncParams<GaussNewtonParams> gncParams;
|
||||||
|
std::vector<size_t> knownInliers;
|
||||||
|
knownInliers.push_back(2);
|
||||||
|
knownInliers.push_back(0);
|
||||||
|
|
||||||
|
std::vector<size_t> knownOutliers;
|
||||||
|
knownOutliers.push_back(3);
|
||||||
|
gncParams.setKnownInliers(knownInliers);
|
||||||
|
gncParams.setKnownOutliers(knownOutliers);
|
||||||
|
|
||||||
|
gncParams.setLossType(GncLossType::TLS);
|
||||||
|
|
||||||
|
Vector weights = 0.5 * Vector::Ones(fg.size());
|
||||||
|
auto gnc = GncOptimizer<GncParams<GaussNewtonParams>>(fg, initial,
|
||||||
|
gncParams);
|
||||||
|
gnc.setWeights(weights);
|
||||||
|
gnc.setInlierCostThresholds(1.0);
|
||||||
|
Values gnc_result = gnc.optimize();
|
||||||
|
CHECK(assert_equal(Point2(0.0, 0.0), gnc_result.at<Point2>(X(1)), 1e-3));
|
||||||
|
|
||||||
|
// check weights were actually fixed:
|
||||||
|
Vector finalWeights = gnc.getWeights();
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[0], tol);
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[1], tol);
|
||||||
|
DOUBLES_EQUAL(1.0, finalWeights[2], tol);
|
||||||
|
DOUBLES_EQUAL(0.0, finalWeights[3], tol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() {
|
int main() {
|
||||||
TestResult tr;
|
TestResult tr;
|
||||||
|
|
Loading…
Reference in New Issue