Adding debugging code from branch in case problems reoccur, will clean this out in the future because it makes the code ugly
parent
a67d974254
commit
b73af0159d
|
|
@ -16,6 +16,7 @@
|
||||||
* @author Richard Roberts, Christian Potthast
|
* @author Richard Roberts, Christian Potthast
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <gtsam/base/debug.h>
|
||||||
#include <gtsam/base/timing.h>
|
#include <gtsam/base/timing.h>
|
||||||
#include <gtsam/linear/GaussianFactor.h>
|
#include <gtsam/linear/GaussianFactor.h>
|
||||||
#include <gtsam/linear/GaussianBayesNet.h>
|
#include <gtsam/linear/GaussianBayesNet.h>
|
||||||
|
|
@ -35,6 +36,8 @@ namespace gtsam {
|
||||||
pair<GaussianBayesNet::shared_ptr, GaussianFactor::shared_ptr> GaussianFactor::CombineAndEliminate(
|
pair<GaussianBayesNet::shared_ptr, GaussianFactor::shared_ptr> GaussianFactor::CombineAndEliminate(
|
||||||
const FactorGraph<GaussianFactor>& factors, size_t nrFrontals, SolveMethod solveMethod) {
|
const FactorGraph<GaussianFactor>& factors, size_t nrFrontals, SolveMethod solveMethod) {
|
||||||
|
|
||||||
|
const bool debug = ISDEBUG("GaussianFactor::CombineAndEliminate");
|
||||||
|
|
||||||
// If any JacobianFactors have constrained noise models, we have to convert
|
// If any JacobianFactors have constrained noise models, we have to convert
|
||||||
// all factors to JacobianFactors. Otherwise, we can convert all factors
|
// all factors to JacobianFactors. Otherwise, we can convert all factors
|
||||||
// to HessianFactors. This is because QR can handle constrained noise
|
// to HessianFactors. This is because QR can handle constrained noise
|
||||||
|
|
@ -58,19 +61,27 @@ namespace gtsam {
|
||||||
|
|
||||||
// Convert all factors to the appropriate type and call the type-specific CombineAndEliminate.
|
// Convert all factors to the appropriate type and call the type-specific CombineAndEliminate.
|
||||||
if(useQR) {
|
if(useQR) {
|
||||||
|
if(debug) cout << "Using QR:";
|
||||||
|
|
||||||
tic(1, "convert to Jacobian");
|
tic(1, "convert to Jacobian");
|
||||||
FactorGraph<JacobianFactor> jacobianFactors;
|
FactorGraph<JacobianFactor> jacobianFactors;
|
||||||
jacobianFactors.reserve(factors.size());
|
jacobianFactors.reserve(factors.size());
|
||||||
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, factors) {
|
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, factors) {
|
||||||
if(factor) {
|
if(factor) {
|
||||||
JacobianFactor::shared_ptr jacobianFactor(boost::dynamic_pointer_cast<JacobianFactor>(factor));
|
JacobianFactor::shared_ptr jacobianFactor(boost::dynamic_pointer_cast<JacobianFactor>(factor));
|
||||||
if(jacobianFactor)
|
if(jacobianFactor) {
|
||||||
jacobianFactors.push_back(jacobianFactor);
|
jacobianFactors.push_back(jacobianFactor);
|
||||||
else {
|
if(debug) jacobianFactor->print("Existing JacobianFactor: ");
|
||||||
|
} else {
|
||||||
HessianFactor::shared_ptr hessianFactor(boost::dynamic_pointer_cast<HessianFactor>(factor));
|
HessianFactor::shared_ptr hessianFactor(boost::dynamic_pointer_cast<HessianFactor>(factor));
|
||||||
if(!hessianFactor) throw std::invalid_argument(
|
if(!hessianFactor) throw std::invalid_argument(
|
||||||
"In GaussianFactor::CombineAndEliminate, factor is neither a JacobianFactor nor a HessianFactor.");
|
"In GaussianFactor::CombineAndEliminate, factor is neither a JacobianFactor nor a HessianFactor.");
|
||||||
jacobianFactors.push_back(JacobianFactor::shared_ptr(new JacobianFactor(*hessianFactor)));
|
jacobianFactors.push_back(JacobianFactor::shared_ptr(new JacobianFactor(*hessianFactor)));
|
||||||
|
if(debug) {
|
||||||
|
cout << "Converted HessianFactor to JacobianFactor:\n";
|
||||||
|
hessianFactor->print("HessianFactor: ");
|
||||||
|
jacobianFactors.back()->print("JacobianFactor: ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -82,8 +93,11 @@ namespace gtsam {
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tic(1, "convert to Hessian");
|
|
||||||
|
const bool checkCholesky = ISDEBUG("GaussianFactor::CombineAndEliminate Check Cholesky");
|
||||||
|
|
||||||
FactorGraph<HessianFactor> hessianFactors;
|
FactorGraph<HessianFactor> hessianFactors;
|
||||||
|
tic(1, "convert to Hessian");
|
||||||
hessianFactors.reserve(factors.size());
|
hessianFactors.reserve(factors.size());
|
||||||
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, factors) {
|
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, factors) {
|
||||||
if(factor) {
|
if(factor) {
|
||||||
|
|
@ -94,15 +108,92 @@ namespace gtsam {
|
||||||
JacobianFactor::shared_ptr jacobianFactor(boost::dynamic_pointer_cast<JacobianFactor>(factor));
|
JacobianFactor::shared_ptr jacobianFactor(boost::dynamic_pointer_cast<JacobianFactor>(factor));
|
||||||
if(!jacobianFactor) throw std::invalid_argument(
|
if(!jacobianFactor) throw std::invalid_argument(
|
||||||
"In GaussianFactor::CombineAndEliminate, factor is neither a JacobianFactor nor a HessianFactor.");
|
"In GaussianFactor::CombineAndEliminate, factor is neither a JacobianFactor nor a HessianFactor.");
|
||||||
hessianFactors.push_back(HessianFactor::shared_ptr(new HessianFactor(*jacobianFactor)));
|
HessianFactor::shared_ptr convertedHessianFactor;
|
||||||
|
try {
|
||||||
|
convertedHessianFactor.reset(new HessianFactor(*jacobianFactor));
|
||||||
|
if(checkCholesky)
|
||||||
|
if(!assert_equal(HessianFactor(*jacobianFactor), HessianFactor(JacobianFactor(*convertedHessianFactor)), 1e-3))
|
||||||
|
throw runtime_error("Conversion between Jacobian and Hessian incorrect");
|
||||||
|
} catch(const exception& e) {
|
||||||
|
cout << "Exception converting to Hessian: " << e.what() << endl;
|
||||||
|
jacobianFactor->print("jacobianFactor: ");
|
||||||
|
convertedHessianFactor->print("convertedHessianFactor: ");
|
||||||
|
SETDEBUG("choleskyPartial", true);
|
||||||
|
SETDEBUG("choleskyCareful", true);
|
||||||
|
HessianFactor(JacobianFactor(*convertedHessianFactor)).print("Jacobian->Hessian->Jacobian->Hessian: ");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
hessianFactors.push_back(convertedHessianFactor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toc(1, "convert to Hessian");
|
toc(1, "convert to Hessian");
|
||||||
tic(2, "Hessian CombineAndEliminate");
|
|
||||||
pair<GaussianBayesNet::shared_ptr, GaussianFactor::shared_ptr> ret(
|
pair<GaussianBayesNet::shared_ptr, GaussianFactor::shared_ptr> ret;
|
||||||
HessianFactor::CombineAndEliminate(hessianFactors, nrFrontals));
|
try {
|
||||||
toc(2, "Hessian CombineAndEliminate");
|
tic(2, "Hessian CombineAndEliminate");
|
||||||
|
ret = HessianFactor::CombineAndEliminate(hessianFactors, nrFrontals);
|
||||||
|
toc(2, "Hessian CombineAndEliminate");
|
||||||
|
} catch(const exception& e) {
|
||||||
|
cout << "Exception in HessianFactor::CombineAndEliminate: " << e.what() << endl;
|
||||||
|
SETDEBUG("HessianFactor::CombineAndEliminate", true);
|
||||||
|
SETDEBUG("updateATA", true);
|
||||||
|
SETDEBUG("JacobianFactor::eliminate", true);
|
||||||
|
SETDEBUG("JacobianFactor::Combine", true);
|
||||||
|
SETDEBUG("choleskyPartial", true);
|
||||||
|
jacobianFactors.print("Jacobian Factors: ");
|
||||||
|
factors.print("Combining factors: ");
|
||||||
|
JacobianFactor::CombineAndEliminate(jacobianFactors, nrFrontals);
|
||||||
|
HessianFactor::CombineAndEliminate(hessianFactors, nrFrontals);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(checkCholesky) {
|
||||||
|
pair<GaussianBayesNet::shared_ptr, GaussianFactor::shared_ptr> expected;
|
||||||
|
FactorGraph<JacobianFactor> jacobianFactors;
|
||||||
|
try {
|
||||||
|
// Compare with QR
|
||||||
|
jacobianFactors.reserve(factors.size());
|
||||||
|
BOOST_FOREACH(const GaussianFactor::shared_ptr& factor, factors) {
|
||||||
|
if(factor) {
|
||||||
|
JacobianFactor::shared_ptr jacobianFactor(boost::dynamic_pointer_cast<JacobianFactor>(factor));
|
||||||
|
if(jacobianFactor)
|
||||||
|
jacobianFactors.push_back(jacobianFactor);
|
||||||
|
else {
|
||||||
|
HessianFactor::shared_ptr hessianFactor(boost::dynamic_pointer_cast<HessianFactor>(factor));
|
||||||
|
if(!hessianFactor) throw std::invalid_argument(
|
||||||
|
"In GaussianFactor::CombineAndEliminate, factor is neither a JacobianFactor nor a HessianFactor.");
|
||||||
|
JacobianFactor::shared_ptr convertedJacobianFactor(new JacobianFactor(*hessianFactor));
|
||||||
|
// if(!assert_equal(*hessianFactor, HessianFactor(*convertedJacobianFactor), 1e-3))
|
||||||
|
// throw runtime_error("Conversion between Jacobian and Hessian incorrect");
|
||||||
|
jacobianFactors.push_back(convertedJacobianFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expected = JacobianFactor::CombineAndEliminate(jacobianFactors, nrFrontals);
|
||||||
|
} catch(...) {
|
||||||
|
cout << "Exception in QR" << endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
HessianFactor actual_factor(*ret.second);
|
||||||
|
HessianFactor expected_factor(*expected.second);
|
||||||
|
if(!assert_equal(*expected.first, *ret.first, 100.0) || !assert_equal(expected_factor, actual_factor, 1.0)) {
|
||||||
|
cout << "Cholesky and QR do not agree" << endl;
|
||||||
|
|
||||||
|
SETDEBUG("HessianFactor::CombineAndEliminate", true);
|
||||||
|
SETDEBUG("updateATA", true);
|
||||||
|
SETDEBUG("JacobianFactor::eliminate", true);
|
||||||
|
SETDEBUG("JacobianFactor::Combine", true);
|
||||||
|
jacobianFactors.print("Jacobian Factors: ");
|
||||||
|
JacobianFactor::CombineAndEliminate(jacobianFactors, nrFrontals);
|
||||||
|
HessianFactor::CombineAndEliminate(hessianFactors, nrFrontals);
|
||||||
|
factors.print("Combining factors: ");
|
||||||
|
|
||||||
|
throw runtime_error("Cholesky and QR do not agree");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue