linear, navigation, std::optional serialization tests
parent
3bac1efd1f
commit
ee65c85442
|
@ -114,10 +114,10 @@ int main(int argc, char* argv[]) {
|
||||||
// The graph stores Factor shared_ptrs, so we cast back to a SmartFactor first
|
// The graph stores Factor shared_ptrs, so we cast back to a SmartFactor first
|
||||||
SmartFactor::shared_ptr smart = boost::dynamic_pointer_cast<SmartFactor>(graph[j]);
|
SmartFactor::shared_ptr smart = boost::dynamic_pointer_cast<SmartFactor>(graph[j]);
|
||||||
if (smart) {
|
if (smart) {
|
||||||
// The output of point() is in boost::optional<Point3>, as sometimes
|
// The output of point() is in std::optional<Point3>, as sometimes
|
||||||
// the triangulation operation inside smart factor will encounter degeneracy.
|
// the triangulation operation inside smart factor will encounter degeneracy.
|
||||||
auto point = smart->point(result);
|
auto point = smart->point(result);
|
||||||
if (point) // ignore if boost::optional return nullptr
|
if (point) // ignore if std::optional return nullptr
|
||||||
landmark_result.insert(j, *point);
|
landmark_result.insert(j, *point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,8 @@ int main(int argc, char* argv[]) {
|
||||||
for (size_t j = 0; j < points.size(); ++j) {
|
for (size_t j = 0; j < points.size(); ++j) {
|
||||||
auto smart = boost::dynamic_pointer_cast<SmartFactor>(graph[j]);
|
auto smart = boost::dynamic_pointer_cast<SmartFactor>(graph[j]);
|
||||||
if (smart) {
|
if (smart) {
|
||||||
boost::optional<Point3> point = smart->point(result);
|
std::optional<Point3> point = smart->point(result);
|
||||||
if (point) // ignore if boost::optional return nullptr
|
if (point) // ignore if std::optional return nullptr
|
||||||
landmark_result.insert(j, *point);
|
landmark_result.insert(j, *point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace gtsam;
|
using namespace gtsam;
|
||||||
|
@ -145,9 +146,9 @@ int main(int argc, char* argv[]) {
|
||||||
cameras, noisyMeasurements, rank_tol, true, measurementNoise, false);
|
cameras, noisyMeasurements, rank_tol, true, measurementNoise, false);
|
||||||
durationDLTOpt += std::chrono::high_resolution_clock::now() - dltOptStart;
|
durationDLTOpt += std::chrono::high_resolution_clock::now() - dltOptStart;
|
||||||
|
|
||||||
errorsLOST.row(i) = *estimateLOST - landmark;
|
errorsLOST.row(i) = estimateLOST - landmark;
|
||||||
errorsDLT.row(i) = *estimateDLT - landmark;
|
errorsDLT.row(i) = estimateDLT - landmark;
|
||||||
errorsDLTOpt.row(i) = *estimateDLTOpt - landmark;
|
errorsDLTOpt.row(i) = estimateDLTOpt - landmark;
|
||||||
}
|
}
|
||||||
PrintCovarianceStats(errorsLOST, "LOST");
|
PrintCovarianceStats(errorsLOST, "LOST");
|
||||||
PrintCovarianceStats(errorsDLT, "DLT");
|
PrintCovarianceStats(errorsDLT, "DLT");
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <gtsam/base/serialization.h>
|
#include <gtsam/base/serialization.h>
|
||||||
|
#include <gtsam/base/TestableAssertions.h>
|
||||||
|
|
||||||
#include <boost/serialization/serialization.hpp>
|
#include <boost/serialization/serialization.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
|
@ -26,24 +26,11 @@ void save(Archive& ar, const std::optional<T>& t, const unsigned int /*version*/
|
||||||
) {
|
) {
|
||||||
// It is an inherent limitation to the serialization of optional.hpp
|
// It is an inherent limitation to the serialization of optional.hpp
|
||||||
// that the underlying type must be either a pointer or must have a
|
// that the underlying type must be either a pointer or must have a
|
||||||
// default constructor. It's possible that this could change sometime
|
// default constructor.
|
||||||
// in the future, but for now, one will have to work around it. This can
|
|
||||||
// be done by serialization the optional<T> as optional<T *>
|
|
||||||
BOOST_STATIC_ASSERT(boost::serialization::detail::is_default_constructible<T>::value || boost::is_pointer<T>::value);
|
BOOST_STATIC_ASSERT(boost::serialization::detail::is_default_constructible<T>::value || boost::is_pointer<T>::value);
|
||||||
const bool tflag = t.has_value();
|
const bool tflag = t.has_value();
|
||||||
ar << boost::serialization::make_nvp("initialized", tflag);
|
ar << boost::serialization::make_nvp("initialized", tflag);
|
||||||
if (tflag) {
|
if (tflag) {
|
||||||
const boost::serialization::item_version_type item_version(version<T>::value);
|
|
||||||
#if 0
|
|
||||||
const boost::archive::library_version_type library_version(
|
|
||||||
ar.get_library_version()
|
|
||||||
};
|
|
||||||
if(boost::archive::library_version_type(3) < library_version){
|
|
||||||
ar << BOOST_SERIALIZATION_NVP(item_version);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ar << BOOST_SERIALIZATION_NVP(item_version);
|
|
||||||
#endif
|
|
||||||
ar << boost::serialization::make_nvp("value", *t);
|
ar << boost::serialization::make_nvp("value", *t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,16 +45,11 @@ void load(Archive& ar, std::optional<T>& t, const unsigned int /*version*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::serialization::item_version_type item_version(0);
|
if (!t.has_value()) {
|
||||||
boost::archive::library_version_type library_version(ar.get_library_version());
|
// Need to be default constructible
|
||||||
if (boost::archive::library_version_type(3) < library_version) {
|
t.emplace();
|
||||||
ar >> BOOST_SERIALIZATION_NVP(item_version);
|
|
||||||
}
|
}
|
||||||
detail::stack_allocate<T> tp;
|
ar >> boost::serialization::make_nvp("value", *t);
|
||||||
ar >> boost::serialization::make_nvp("value", tp.reference());
|
|
||||||
t = std::move(tp.reference());
|
|
||||||
// hack because std::optional does not have get_ptr fn
|
|
||||||
ar.reset_object_address(&(t.value()), &tp.reference());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive, class T>
|
template <class Archive, class T>
|
||||||
|
@ -75,6 +57,8 @@ void serialize(Archive& ar, std::optional<T>& t, const unsigned int version) {
|
||||||
boost::serialization::split_free(ar, t, version);
|
boost::serialization::split_free(ar, t, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// derive boost::xml_archive_impl for archiving std::optional<T> with xml
|
||||||
|
|
||||||
} // namespace serialization
|
} // namespace serialization
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include <CppUnitLite/TestHarness.h>
|
||||||
|
|
||||||
|
#include <boost/archive/binary_iarchive.hpp>
|
||||||
|
#include <boost/archive/binary_oarchive.hpp>
|
||||||
|
#include <boost/archive/xml_iarchive.hpp>
|
||||||
|
#include <boost/archive/xml_oarchive.hpp>
|
||||||
|
|
||||||
|
#include "gtsam/base/serializationTestHelpers.h"
|
||||||
|
#include "gtsam/base/std_optional_serialization.h"
|
||||||
|
|
||||||
|
using namespace gtsam;
|
||||||
|
|
||||||
|
// A test to check that the serialization of std::optional works with boost
|
||||||
|
TEST(StdOptionalSerialization, SerializeIntOptional) {
|
||||||
|
// Create an optional
|
||||||
|
std::optional<int> opt(42);
|
||||||
|
|
||||||
|
// Serialize it
|
||||||
|
std::stringstream ss;
|
||||||
|
boost::archive::text_oarchive oa(ss);
|
||||||
|
oa << opt;
|
||||||
|
|
||||||
|
// Deserialize it
|
||||||
|
std::optional<int> opt2;
|
||||||
|
boost::archive::text_iarchive ia(ss);
|
||||||
|
ia >> opt2;
|
||||||
|
|
||||||
|
// Check that it worked
|
||||||
|
EXPECT(opt2.has_value());
|
||||||
|
EXPECT(*opt2 == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A test to check if we serialize an empty optional, it is deserialized as an
|
||||||
|
// empty optional
|
||||||
|
TEST(StdOptionalSerialization, SerializeEmptyOptional) {
|
||||||
|
// Create an optional
|
||||||
|
std::optional<int> opt;
|
||||||
|
|
||||||
|
// Serialize it
|
||||||
|
std::stringstream ss;
|
||||||
|
boost::archive::text_oarchive oa(ss);
|
||||||
|
oa << opt;
|
||||||
|
|
||||||
|
// Deserialize it
|
||||||
|
std::optional<int> opt2 = 43;
|
||||||
|
boost::archive::text_iarchive ia(ss);
|
||||||
|
ia >> opt2;
|
||||||
|
|
||||||
|
// Check that it worked
|
||||||
|
EXPECT(!opt2.has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
// Implement the equals trait for TestOptionalStruct
|
||||||
|
namespace gtsam {
|
||||||
|
// A struct which contains an optional
|
||||||
|
class TestOptionalStruct {
|
||||||
|
public:
|
||||||
|
std::optional<int> opt;
|
||||||
|
TestOptionalStruct() = default;
|
||||||
|
TestOptionalStruct(const int& opt)
|
||||||
|
: opt(opt) {}
|
||||||
|
friend class boost::serialization::access;
|
||||||
|
template <class Archive>
|
||||||
|
void serialize(Archive& ar, const unsigned int /*version*/) {
|
||||||
|
ar& BOOST_SERIALIZATION_NVP(opt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct traits<TestOptionalStruct> {
|
||||||
|
static bool Equals(const TestOptionalStruct& q1, const TestOptionalStruct& q2, double) {
|
||||||
|
// if both have values then compare the values
|
||||||
|
if (q1.opt.has_value() && q2.opt.has_value()) {
|
||||||
|
return *q1.opt == *q2.opt;
|
||||||
|
}
|
||||||
|
// otherwise check that both are empty
|
||||||
|
return q1.opt == q2.opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Print(const TestOptionalStruct& m, const std::string& s = "") {
|
||||||
|
/* std::cout << s << "opt: " << m.opt << std::endl; */
|
||||||
|
if (m.opt.has_value()) {
|
||||||
|
std::cout << s << "opt: " << *m.opt << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << s << "opt: empty" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace gtsam
|
||||||
|
|
||||||
|
// Test for a struct with an initialized optional
|
||||||
|
TEST(StdOptionalSerialization, SerializTestOptionalStruct) {
|
||||||
|
TestOptionalStruct optStruct(10);
|
||||||
|
EXPECT(serializationTestHelpers::equalsObj(optStruct));
|
||||||
|
EXPECT(serializationTestHelpers::equalsXML(optStruct));
|
||||||
|
EXPECT(serializationTestHelpers::equalsBinary(optStruct));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for a struct with an uninitialized optional
|
||||||
|
TEST(StdOptionalSerialization, SerializTestOptionalStructUninitialized) {
|
||||||
|
TestOptionalStruct optStruct;
|
||||||
|
EXPECT(serializationTestHelpers::equalsObj(optStruct));
|
||||||
|
EXPECT(serializationTestHelpers::equalsXML(optStruct));
|
||||||
|
EXPECT(serializationTestHelpers::equalsBinary(optStruct));
|
||||||
|
}
|
||||||
|
int main() {
|
||||||
|
TestResult tr;
|
||||||
|
return TestRegistry::runAllTests(tr);
|
||||||
|
}
|
|
@ -60,11 +60,11 @@ class AcceleratedPowerMethod : public PowerMethod<Operator> {
|
||||||
* vector as ritzVector
|
* vector as ritzVector
|
||||||
*/
|
*/
|
||||||
explicit AcceleratedPowerMethod(
|
explicit AcceleratedPowerMethod(
|
||||||
const Operator &A, const boost::optional<Vector> initial = boost::none,
|
const Operator &A, const std::optional<Vector> initial = {},
|
||||||
double initialBeta = 0.0)
|
double initialBeta = 0.0)
|
||||||
: PowerMethod<Operator>(A, initial) {
|
: PowerMethod<Operator>(A, initial) {
|
||||||
// initialize Ritz eigen vector and previous vector
|
// initialize Ritz eigen vector and previous vector
|
||||||
this->ritzVector_ = initial ? initial.get() : Vector::Random(this->dim_);
|
this->ritzVector_ = initial ? *initial : Vector::Random(this->dim_);
|
||||||
this->ritzVector_.normalize();
|
this->ritzVector_.normalize();
|
||||||
previousVector_ = Vector::Zero(this->dim_);
|
previousVector_ = Vector::Zero(this->dim_);
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,11 @@
|
||||||
|
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,7 @@ void JacobianFactor::JacobianFactorHelper(const GaussianFactorGraph& graph,
|
||||||
// Copy the RHS vectors and sigmas
|
// Copy the RHS vectors and sigmas
|
||||||
gttic(copy_vectors);
|
gttic(copy_vectors);
|
||||||
bool anyConstrained = false;
|
bool anyConstrained = false;
|
||||||
boost::optional<Vector> sigmas;
|
std::optional<Vector> sigmas;
|
||||||
// Loop over source jacobians
|
// Loop over source jacobians
|
||||||
DenseIndex nextRow = 0;
|
DenseIndex nextRow = 0;
|
||||||
for (size_t factorI = 0; factorI < jacobians.size(); ++factorI) {
|
for (size_t factorI = 0; factorI < jacobians.size(); ++factorI) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ void updateAb(MATRIX& Ab, int j, const Vector& a, const Vector& rd) {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// check *above the diagonal* for non-zero entries
|
// check *above the diagonal* for non-zero entries
|
||||||
boost::optional<Vector> checkIfDiagonal(const Matrix& M) {
|
std::optional<Vector> checkIfDiagonal(const Matrix& M) {
|
||||||
size_t m = M.rows(), n = M.cols();
|
size_t m = M.rows(), n = M.cols();
|
||||||
assert(m > 0);
|
assert(m > 0);
|
||||||
// check all non-diagonal entries
|
// check all non-diagonal entries
|
||||||
|
@ -61,7 +61,7 @@ boost::optional<Vector> checkIfDiagonal(const Matrix& M) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (full) {
|
if (full) {
|
||||||
return boost::none;
|
return {};
|
||||||
} else {
|
} else {
|
||||||
Vector diagonal(n);
|
Vector diagonal(n);
|
||||||
for (j = 0; j < n; j++)
|
for (j = 0; j < n; j++)
|
||||||
|
@ -88,7 +88,7 @@ Gaussian::shared_ptr Gaussian::SqrtInformation(const Matrix& R, bool smart) {
|
||||||
if (m != n)
|
if (m != n)
|
||||||
throw invalid_argument("Gaussian::SqrtInformation: R not square");
|
throw invalid_argument("Gaussian::SqrtInformation: R not square");
|
||||||
if (smart) {
|
if (smart) {
|
||||||
boost::optional<Vector> diagonal = checkIfDiagonal(R);
|
std::optional<Vector> diagonal = checkIfDiagonal(R);
|
||||||
if (diagonal)
|
if (diagonal)
|
||||||
return Diagonal::Sigmas(diagonal->array().inverse(), true);
|
return Diagonal::Sigmas(diagonal->array().inverse(), true);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ Gaussian::shared_ptr Gaussian::Information(const Matrix& information, bool smart
|
||||||
size_t m = information.rows(), n = information.cols();
|
size_t m = information.rows(), n = information.cols();
|
||||||
if (m != n)
|
if (m != n)
|
||||||
throw invalid_argument("Gaussian::Information: R not square");
|
throw invalid_argument("Gaussian::Information: R not square");
|
||||||
boost::optional<Vector> diagonal = boost::none;
|
std::optional<Vector> diagonal = {};
|
||||||
if (smart)
|
if (smart)
|
||||||
diagonal = checkIfDiagonal(information);
|
diagonal = checkIfDiagonal(information);
|
||||||
if (diagonal)
|
if (diagonal)
|
||||||
|
@ -119,7 +119,7 @@ Gaussian::shared_ptr Gaussian::Covariance(const Matrix& covariance,
|
||||||
size_t m = covariance.rows(), n = covariance.cols();
|
size_t m = covariance.rows(), n = covariance.cols();
|
||||||
if (m != n)
|
if (m != n)
|
||||||
throw invalid_argument("Gaussian::Covariance: covariance not square");
|
throw invalid_argument("Gaussian::Covariance: covariance not square");
|
||||||
boost::optional<Vector> variances = boost::none;
|
std::optional<Vector> variances = {};
|
||||||
if (smart)
|
if (smart)
|
||||||
variances = checkIfDiagonal(covariance);
|
variances = checkIfDiagonal(covariance);
|
||||||
if (variances)
|
if (variances)
|
||||||
|
@ -426,8 +426,8 @@ Constrained::shared_ptr Constrained::unit() const {
|
||||||
// Check whether column a triggers a constraint and corresponding variable is deterministic
|
// Check whether column a triggers a constraint and corresponding variable is deterministic
|
||||||
// Return constraint_row with maximum element in case variable plays in multiple constraints
|
// Return constraint_row with maximum element in case variable plays in multiple constraints
|
||||||
template <typename VECTOR>
|
template <typename VECTOR>
|
||||||
boost::optional<size_t> check_if_constraint(VECTOR a, const Vector& invsigmas, size_t m) {
|
std::optional<size_t> check_if_constraint(VECTOR a, const Vector& invsigmas, size_t m) {
|
||||||
boost::optional<size_t> constraint_row;
|
std::optional<size_t> constraint_row;
|
||||||
// not zero, so roundoff errors will not be counted
|
// not zero, so roundoff errors will not be counted
|
||||||
// TODO(frank): that's a fairly crude way of dealing with roundoff errors :-(
|
// TODO(frank): that's a fairly crude way of dealing with roundoff errors :-(
|
||||||
double max_element = 1e-9;
|
double max_element = 1e-9;
|
||||||
|
@ -437,7 +437,7 @@ boost::optional<size_t> check_if_constraint(VECTOR a, const Vector& invsigmas, s
|
||||||
double abs_ai = std::abs(a(i,0));
|
double abs_ai = std::abs(a(i,0));
|
||||||
if (abs_ai > max_element) {
|
if (abs_ai > max_element) {
|
||||||
max_element = abs_ai;
|
max_element = abs_ai;
|
||||||
constraint_row.reset(i);
|
constraint_row = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return constraint_row;
|
return constraint_row;
|
||||||
|
@ -468,7 +468,7 @@ SharedDiagonal Constrained::QR(Matrix& Ab) const {
|
||||||
Eigen::Block<Matrix> a = Ab.block(0, j, m, 1);
|
Eigen::Block<Matrix> a = Ab.block(0, j, m, 1);
|
||||||
|
|
||||||
// Check whether we need to handle as a constraint
|
// Check whether we need to handle as a constraint
|
||||||
boost::optional<size_t> constraint_row = check_if_constraint(a, invsigmas, m);
|
std::optional<size_t> constraint_row = check_if_constraint(a, invsigmas, m);
|
||||||
|
|
||||||
if (constraint_row) {
|
if (constraint_row) {
|
||||||
// Handle this as a constraint, as the i^th row has zero sigma with non-zero entry A(i,j)
|
// Handle this as a constraint, as the i^th row has zero sigma with non-zero entry A(i,j)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <gtsam/base/Testable.h>
|
#include <gtsam/base/Testable.h>
|
||||||
#include <gtsam/base/Matrix.h>
|
#include <gtsam/base/Matrix.h>
|
||||||
|
#include <gtsam/base/std_optional_serialization.h>
|
||||||
#include <gtsam/dllexport.h>
|
#include <gtsam/dllexport.h>
|
||||||
#include <gtsam/linear/LossFunctions.h>
|
#include <gtsam/linear/LossFunctions.h>
|
||||||
|
|
||||||
|
@ -27,7 +28,8 @@
|
||||||
#include <boost/serialization/extended_type_info.hpp>
|
#include <boost/serialization/extended_type_info.hpp>
|
||||||
#include <boost/serialization/singleton.hpp>
|
#include <boost/serialization/singleton.hpp>
|
||||||
#include <boost/serialization/shared_ptr.hpp>
|
#include <boost/serialization/shared_ptr.hpp>
|
||||||
#include <boost/serialization/optional.hpp>
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -164,7 +166,7 @@ namespace gtsam {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Matrix square root of information matrix (R) */
|
/** Matrix square root of information matrix (R) */
|
||||||
boost::optional<Matrix> sqrt_information_;
|
std::optional<Matrix> sqrt_information_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -184,7 +186,7 @@ namespace gtsam {
|
||||||
|
|
||||||
/** constructor takes square root information matrix */
|
/** constructor takes square root information matrix */
|
||||||
Gaussian(size_t dim = 1,
|
Gaussian(size_t dim = 1,
|
||||||
const boost::optional<Matrix>& sqrt_information = boost::none)
|
const std::optional<Matrix>& sqrt_information = {})
|
||||||
: Base(dim), sqrt_information_(sqrt_information) {}
|
: Base(dim), sqrt_information_(sqrt_information) {}
|
||||||
|
|
||||||
~Gaussian() override {}
|
~Gaussian() override {}
|
||||||
|
@ -732,7 +734,7 @@ namespace gtsam {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function
|
// Helper function
|
||||||
GTSAM_EXPORT boost::optional<Vector> checkIfDiagonal(const Matrix& M);
|
GTSAM_EXPORT std::optional<Vector> checkIfDiagonal(const Matrix& M);
|
||||||
|
|
||||||
} // namespace noiseModel
|
} // namespace noiseModel
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <Eigen/Sparse>
|
#include <Eigen/Sparse>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -75,10 +76,10 @@ class PowerMethod {
|
||||||
|
|
||||||
/// Construct from the aim matrix and intial ritz vector
|
/// Construct from the aim matrix and intial ritz vector
|
||||||
explicit PowerMethod(const Operator &A,
|
explicit PowerMethod(const Operator &A,
|
||||||
const boost::optional<Vector> initial = boost::none)
|
const std::optional<Vector> initial = {})
|
||||||
: A_(A), dim_(A.rows()), nrIterations_(0) {
|
: A_(A), dim_(A.rows()), nrIterations_(0) {
|
||||||
Vector x0;
|
Vector x0;
|
||||||
x0 = initial ? initial.get() : Vector::Random(dim_);
|
x0 = initial ? *initial : Vector::Random(dim_);
|
||||||
x0.normalize();
|
x0.normalize();
|
||||||
|
|
||||||
// initialize Ritz eigen value
|
// initialize Ritz eigen value
|
||||||
|
|
|
@ -185,7 +185,7 @@ Rot3 AHRSFactor::Predict(const Rot3& rot_i, const Vector3& bias,
|
||||||
AHRSFactor::AHRSFactor(Key rot_i, Key rot_j, Key bias,
|
AHRSFactor::AHRSFactor(Key rot_i, Key rot_j, Key bias,
|
||||||
const PreintegratedAhrsMeasurements& pim,
|
const PreintegratedAhrsMeasurements& pim,
|
||||||
const Vector3& omegaCoriolis,
|
const Vector3& omegaCoriolis,
|
||||||
const boost::optional<Pose3>& body_P_sensor)
|
const std::optional<Pose3>& body_P_sensor)
|
||||||
: Base(noiseModel::Gaussian::Covariance(pim.preintMeasCov_), rot_i, rot_j,
|
: Base(noiseModel::Gaussian::Covariance(pim.preintMeasCov_), rot_i, rot_j,
|
||||||
bias),
|
bias),
|
||||||
_PIM_(pim) {
|
_PIM_(pim) {
|
||||||
|
@ -198,7 +198,7 @@ AHRSFactor::AHRSFactor(Key rot_i, Key rot_j, Key bias,
|
||||||
Rot3 AHRSFactor::predict(const Rot3& rot_i, const Vector3& bias,
|
Rot3 AHRSFactor::predict(const Rot3& rot_i, const Vector3& bias,
|
||||||
const PreintegratedAhrsMeasurements& pim,
|
const PreintegratedAhrsMeasurements& pim,
|
||||||
const Vector3& omegaCoriolis,
|
const Vector3& omegaCoriolis,
|
||||||
const boost::optional<Pose3>& body_P_sensor) {
|
const std::optional<Pose3>& body_P_sensor) {
|
||||||
auto p = boost::make_shared<PreintegratedAhrsMeasurements::Params>(pim.p());
|
auto p = boost::make_shared<PreintegratedAhrsMeasurements::Params>(pim.p());
|
||||||
p->omegaCoriolis = omegaCoriolis;
|
p->omegaCoriolis = omegaCoriolis;
|
||||||
p->body_P_sensor = body_P_sensor;
|
p->body_P_sensor = body_P_sensor;
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include <gtsam/nonlinear/NonlinearFactor.h>
|
#include <gtsam/nonlinear/NonlinearFactor.h>
|
||||||
#include <gtsam/geometry/Pose3.h>
|
#include <gtsam/geometry/Pose3.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,13 +196,13 @@ public:
|
||||||
AHRSFactor(Key rot_i, Key rot_j, Key bias,
|
AHRSFactor(Key rot_i, Key rot_j, Key bias,
|
||||||
const PreintegratedAhrsMeasurements& pim,
|
const PreintegratedAhrsMeasurements& pim,
|
||||||
const Vector3& omegaCoriolis,
|
const Vector3& omegaCoriolis,
|
||||||
const boost::optional<Pose3>& body_P_sensor = boost::none);
|
const std::optional<Pose3>& body_P_sensor = {});
|
||||||
|
|
||||||
/// @deprecated static function, but used in tests.
|
/// @deprecated static function, but used in tests.
|
||||||
static Rot3 predict(
|
static Rot3 predict(
|
||||||
const Rot3& rot_i, const Vector3& bias,
|
const Rot3& rot_i, const Vector3& bias,
|
||||||
const PreintegratedAhrsMeasurements& pim, const Vector3& omegaCoriolis,
|
const PreintegratedAhrsMeasurements& pim, const Vector3& omegaCoriolis,
|
||||||
const boost::optional<Pose3>& body_P_sensor = boost::none);
|
const std::optional<Pose3>& body_P_sensor = {});
|
||||||
|
|
||||||
#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V42
|
#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V42
|
||||||
/// @deprecated name
|
/// @deprecated name
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace imuBias {
|
||||||
// // H1: Jacobian w.r.t. IMUBias
|
// // H1: Jacobian w.r.t. IMUBias
|
||||||
// // H2: Jacobian w.r.t. pose
|
// // H2: Jacobian w.r.t. pose
|
||||||
// Vector CorrectGyroWithEarthRotRate(Vector measurement, const Pose3& pose, const Vector& w_earth_rate_G,
|
// Vector CorrectGyroWithEarthRotRate(Vector measurement, const Pose3& pose, const Vector& w_earth_rate_G,
|
||||||
// boost::optional<Matrix&> H1=boost::none, boost::optional<Matrix&> H2=boost::none) const {
|
// Matrix* H1=nullptr, Matrix* H2=nullptr) const {
|
||||||
//
|
//
|
||||||
// Matrix R_G_to_I( pose.rotation().matrix().transpose() );
|
// Matrix R_G_to_I( pose.rotation().matrix().transpose() );
|
||||||
// Vector w_earth_rate_I = R_G_to_I * w_earth_rate_G;
|
// Vector w_earth_rate_I = R_G_to_I * w_earth_rate_G;
|
||||||
|
|
|
@ -11,9 +11,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtsam/base/std_optional_serialization.h>
|
||||||
#include <gtsam/geometry/concepts.h>
|
#include <gtsam/geometry/concepts.h>
|
||||||
#include <gtsam/nonlinear/NonlinearFactor.h>
|
#include <gtsam/nonlinear/NonlinearFactor.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,7 +38,7 @@ class MagPoseFactor: public NoiseModelFactorN<POSE> {
|
||||||
const Point measured_; ///< The measured magnetometer data in the body frame.
|
const Point measured_; ///< The measured magnetometer data in the body frame.
|
||||||
const Point nM_; ///< Local magnetic field (mag output units) in the nav frame.
|
const Point nM_; ///< Local magnetic field (mag output units) in the nav frame.
|
||||||
const Point bias_; ///< The bias vector (mag output units) in the body frame.
|
const Point bias_; ///< The bias vector (mag output units) in the body frame.
|
||||||
boost::optional<POSE> body_P_sensor_; ///< The pose of the sensor in the body frame.
|
std::optional<POSE> body_P_sensor_; ///< The pose of the sensor in the body frame.
|
||||||
|
|
||||||
static const int MeasDim = Point::RowsAtCompileTime;
|
static const int MeasDim = Point::RowsAtCompileTime;
|
||||||
static const int PoseDim = traits<POSE>::dimension;
|
static const int PoseDim = traits<POSE>::dimension;
|
||||||
|
@ -74,7 +77,7 @@ class MagPoseFactor: public NoiseModelFactorN<POSE> {
|
||||||
const Point& direction,
|
const Point& direction,
|
||||||
const Point& bias,
|
const Point& bias,
|
||||||
const SharedNoiseModel& model,
|
const SharedNoiseModel& model,
|
||||||
const boost::optional<POSE>& body_P_sensor)
|
const std::optional<POSE>& body_P_sensor)
|
||||||
: Base(model, pose_key),
|
: Base(model, pose_key),
|
||||||
measured_(body_P_sensor ? body_P_sensor->rotation() * measured : measured),
|
measured_(body_P_sensor ? body_P_sensor->rotation() * measured : measured),
|
||||||
nM_(scale * direction.normalized()),
|
nM_(scale * direction.normalized()),
|
||||||
|
|
|
@ -256,7 +256,7 @@ Vector9 NavState::coriolis(double dt, const Vector3& omega, bool secondOrder,
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Vector9 NavState::correctPIM(const Vector9& pim, double dt,
|
Vector9 NavState::correctPIM(const Vector9& pim, double dt,
|
||||||
const Vector3& n_gravity, const boost::optional<Vector3>& omegaCoriolis,
|
const Vector3& n_gravity, const std::optional<Vector3>& omegaCoriolis,
|
||||||
bool use2ndOrderCoriolis, OptionalJacobian<9, 9> H1,
|
bool use2ndOrderCoriolis, OptionalJacobian<9, 9> H1,
|
||||||
OptionalJacobian<9, 9> H2) const {
|
OptionalJacobian<9, 9> H2) const {
|
||||||
const Rot3& nRb = R_;
|
const Rot3& nRb = R_;
|
||||||
|
|
|
@ -79,9 +79,9 @@ public:
|
||||||
/// @name Component Access
|
/// @name Component Access
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
const Rot3& attitude(OptionalJacobian<3, 9> H = boost::none) const;
|
const Rot3& attitude(OptionalJacobian<3, 9> H = {}) const;
|
||||||
const Point3& position(OptionalJacobian<3, 9> H = boost::none) const;
|
const Point3& position(OptionalJacobian<3, 9> H = {}) const;
|
||||||
const Velocity3& velocity(OptionalJacobian<3, 9> H = boost::none) const;
|
const Velocity3& velocity(OptionalJacobian<3, 9> H = {}) const;
|
||||||
|
|
||||||
const Pose3 pose() const {
|
const Pose3 pose() const {
|
||||||
return Pose3(attitude(), position());
|
return Pose3(attitude(), position());
|
||||||
|
@ -108,7 +108,7 @@ public:
|
||||||
return v_;
|
return v_;
|
||||||
}
|
}
|
||||||
// Return velocity in body frame
|
// Return velocity in body frame
|
||||||
Velocity3 bodyVelocity(OptionalJacobian<3, 9> H = boost::none) const;
|
Velocity3 bodyVelocity(OptionalJacobian<3, 9> H = {}) const;
|
||||||
|
|
||||||
/// Return matrix group representation, in MATLAB notation:
|
/// Return matrix group representation, in MATLAB notation:
|
||||||
/// nTb = [nRb 0 n_t; 0 nRb n_v; 0 0 1]
|
/// nTb = [nRb 0 n_t; 0 nRb n_v; 0 0 1]
|
||||||
|
@ -156,13 +156,13 @@ public:
|
||||||
|
|
||||||
/// retract with optional derivatives
|
/// retract with optional derivatives
|
||||||
NavState retract(const Vector9& v, //
|
NavState retract(const Vector9& v, //
|
||||||
OptionalJacobian<9, 9> H1 = boost::none, OptionalJacobian<9, 9> H2 =
|
OptionalJacobian<9, 9> H1 = {}, OptionalJacobian<9, 9> H2 =
|
||||||
boost::none) const;
|
{}) const;
|
||||||
|
|
||||||
/// localCoordinates with optional derivatives
|
/// localCoordinates with optional derivatives
|
||||||
Vector9 localCoordinates(const NavState& g, //
|
Vector9 localCoordinates(const NavState& g, //
|
||||||
OptionalJacobian<9, 9> H1 = boost::none, OptionalJacobian<9, 9> H2 =
|
OptionalJacobian<9, 9> H1 = {}, OptionalJacobian<9, 9> H2 =
|
||||||
boost::none) const;
|
{}) const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Dynamics
|
/// @name Dynamics
|
||||||
|
@ -176,14 +176,14 @@ public:
|
||||||
|
|
||||||
/// Compute tangent space contribution due to Coriolis forces
|
/// Compute tangent space contribution due to Coriolis forces
|
||||||
Vector9 coriolis(double dt, const Vector3& omega, bool secondOrder = false,
|
Vector9 coriolis(double dt, const Vector3& omega, bool secondOrder = false,
|
||||||
OptionalJacobian<9, 9> H = boost::none) const;
|
OptionalJacobian<9, 9> H = {}) const;
|
||||||
|
|
||||||
/// Correct preintegrated tangent vector with our velocity and rotated gravity,
|
/// Correct preintegrated tangent vector with our velocity and rotated gravity,
|
||||||
/// taking into account Coriolis forces if omegaCoriolis is given.
|
/// taking into account Coriolis forces if omegaCoriolis is given.
|
||||||
Vector9 correctPIM(const Vector9& pim, double dt, const Vector3& n_gravity,
|
Vector9 correctPIM(const Vector9& pim, double dt, const Vector3& n_gravity,
|
||||||
const boost::optional<Vector3>& omegaCoriolis, bool use2ndOrderCoriolis =
|
const std::optional<Vector3>& omegaCoriolis, bool use2ndOrderCoriolis =
|
||||||
false, OptionalJacobian<9, 9> H1 = boost::none,
|
false, OptionalJacobian<9, 9> H1 = {},
|
||||||
OptionalJacobian<9, 9> H2 = boost::none) const;
|
OptionalJacobian<9, 9> H2 = {}) const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,7 @@ void PreintegratedRotation::integrateMeasurement(const Vector3& measuredOmega,
|
||||||
Rot3 PreintegratedRotation::biascorrectedDeltaRij(const Vector3& biasOmegaIncr,
|
Rot3 PreintegratedRotation::biascorrectedDeltaRij(const Vector3& biasOmegaIncr,
|
||||||
OptionalJacobian<3, 3> H) const {
|
OptionalJacobian<3, 3> H) const {
|
||||||
const Vector3 biasInducedOmega = delRdelBiasOmega_ * biasOmegaIncr;
|
const Vector3 biasInducedOmega = delRdelBiasOmega_ * biasOmegaIncr;
|
||||||
const Rot3 deltaRij_biascorrected = deltaRij_.expmap(biasInducedOmega,
|
const Rot3 deltaRij_biascorrected = deltaRij_.expmap(biasInducedOmega,{}, H);
|
||||||
boost::none, H);
|
|
||||||
if (H)
|
if (H)
|
||||||
(*H) *= delRdelBiasOmega_;
|
(*H) *= delRdelBiasOmega_;
|
||||||
return deltaRij_biascorrected;
|
return deltaRij_biascorrected;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <gtsam/geometry/Pose3.h>
|
#include <gtsam/geometry/Pose3.h>
|
||||||
#include <gtsam/base/Matrix.h>
|
#include <gtsam/base/Matrix.h>
|
||||||
|
#include <gtsam/base/std_optional_serialization.h>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -32,16 +33,17 @@ struct GTSAM_EXPORT PreintegratedRotationParams {
|
||||||
/// Continuous-time "Covariance" of gyroscope measurements
|
/// Continuous-time "Covariance" of gyroscope measurements
|
||||||
/// The units for stddev are σ = rad/s/√Hz
|
/// The units for stddev are σ = rad/s/√Hz
|
||||||
Matrix3 gyroscopeCovariance;
|
Matrix3 gyroscopeCovariance;
|
||||||
boost::optional<Vector3> omegaCoriolis; ///< Coriolis constant
|
std::optional<Vector3> omegaCoriolis; ///< Coriolis constant
|
||||||
boost::optional<Pose3> body_P_sensor; ///< The pose of the sensor in the body frame
|
std::optional<Pose3> body_P_sensor; ///< The pose of the sensor in the body frame
|
||||||
|
|
||||||
PreintegratedRotationParams() : gyroscopeCovariance(I_3x3) {}
|
PreintegratedRotationParams() : gyroscopeCovariance(I_3x3) {}
|
||||||
|
|
||||||
PreintegratedRotationParams(const Matrix3& gyroscope_covariance,
|
PreintegratedRotationParams(const Matrix3& gyroscope_covariance,
|
||||||
boost::optional<Vector3> omega_coriolis)
|
std::optional<Vector3> omega_coriolis)
|
||||||
: gyroscopeCovariance(gyroscope_covariance) {
|
: gyroscopeCovariance(gyroscope_covariance) {
|
||||||
if (omega_coriolis)
|
if (omega_coriolis) {
|
||||||
omegaCoriolis.reset(omega_coriolis.get());
|
omegaCoriolis = *omega_coriolis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~PreintegratedRotationParams() {}
|
virtual ~PreintegratedRotationParams() {}
|
||||||
|
@ -50,12 +52,12 @@ struct GTSAM_EXPORT PreintegratedRotationParams {
|
||||||
virtual bool equals(const PreintegratedRotationParams& other, double tol=1e-9) const;
|
virtual bool equals(const PreintegratedRotationParams& other, double tol=1e-9) const;
|
||||||
|
|
||||||
void setGyroscopeCovariance(const Matrix3& cov) { gyroscopeCovariance = cov; }
|
void setGyroscopeCovariance(const Matrix3& cov) { gyroscopeCovariance = cov; }
|
||||||
void setOmegaCoriolis(const Vector3& omega) { omegaCoriolis.reset(omega); }
|
void setOmegaCoriolis(const Vector3& omega) { omegaCoriolis = omega; }
|
||||||
void setBodyPSensor(const Pose3& pose) { body_P_sensor.reset(pose); }
|
void setBodyPSensor(const Pose3& pose) { body_P_sensor = pose; }
|
||||||
|
|
||||||
const Matrix3& getGyroscopeCovariance() const { return gyroscopeCovariance; }
|
const Matrix3& getGyroscopeCovariance() const { return gyroscopeCovariance; }
|
||||||
boost::optional<Vector3> getOmegaCoriolis() const { return omegaCoriolis; }
|
std::optional<Vector3> getOmegaCoriolis() const { return omegaCoriolis; }
|
||||||
boost::optional<Pose3> getBodyPSensor() const { return body_P_sensor; }
|
std::optional<Pose3> getBodyPSensor() const { return body_P_sensor; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Serialization function */
|
/** Serialization function */
|
||||||
|
@ -66,8 +68,8 @@ struct GTSAM_EXPORT PreintegratedRotationParams {
|
||||||
ar & BOOST_SERIALIZATION_NVP(gyroscopeCovariance);
|
ar & BOOST_SERIALIZATION_NVP(gyroscopeCovariance);
|
||||||
ar & BOOST_SERIALIZATION_NVP(body_P_sensor);
|
ar & BOOST_SERIALIZATION_NVP(body_P_sensor);
|
||||||
|
|
||||||
// Provide support for Eigen::Matrix in boost::optional
|
// Provide support for Eigen::Matrix in std::optional
|
||||||
bool omegaCoriolisFlag = omegaCoriolis.is_initialized();
|
bool omegaCoriolisFlag = omegaCoriolis.has_value();
|
||||||
ar & boost::serialization::make_nvp("omegaCoriolisFlag", omegaCoriolisFlag);
|
ar & boost::serialization::make_nvp("omegaCoriolisFlag", omegaCoriolisFlag);
|
||||||
if (omegaCoriolisFlag) {
|
if (omegaCoriolisFlag) {
|
||||||
ar & BOOST_SERIALIZATION_NVP(*omegaCoriolis);
|
ar & BOOST_SERIALIZATION_NVP(*omegaCoriolis);
|
||||||
|
@ -164,12 +166,12 @@ class GTSAM_EXPORT PreintegratedRotation {
|
||||||
/// Calculate an incremental rotation given the gyro measurement and a time interval,
|
/// Calculate an incremental rotation given the gyro measurement and a time interval,
|
||||||
/// and update both deltaTij_ and deltaRij_.
|
/// and update both deltaTij_ and deltaRij_.
|
||||||
void integrateMeasurement(const Vector3& measuredOmega, const Vector3& biasHat, double deltaT,
|
void integrateMeasurement(const Vector3& measuredOmega, const Vector3& biasHat, double deltaT,
|
||||||
OptionalJacobian<3, 3> D_incrR_integratedOmega = boost::none,
|
OptionalJacobian<3, 3> D_incrR_integratedOmega = {},
|
||||||
OptionalJacobian<3, 3> F = boost::none);
|
OptionalJacobian<3, 3> F = {});
|
||||||
|
|
||||||
/// Return a bias corrected version of the integrated rotation, with optional Jacobian
|
/// Return a bias corrected version of the integrated rotation, with optional Jacobian
|
||||||
Rot3 biascorrectedDeltaRij(const Vector3& biasOmegaIncr,
|
Rot3 biascorrectedDeltaRij(const Vector3& biasOmegaIncr,
|
||||||
OptionalJacobian<3, 3> H = boost::none) const;
|
OptionalJacobian<3, 3> H = {}) const;
|
||||||
|
|
||||||
/// Integrate coriolis correction in body frame rot_i
|
/// Integrate coriolis correction in body frame rot_i
|
||||||
Vector3 integrateCoriolis(const Rot3& rot_i) const;
|
Vector3 integrateCoriolis(const Rot3& rot_i) const;
|
||||||
|
|
|
@ -129,9 +129,9 @@ class GTSAM_EXPORT PreintegrationBase {
|
||||||
*/
|
*/
|
||||||
std::pair<Vector3, Vector3> correctMeasurementsBySensorPose(
|
std::pair<Vector3, Vector3> correctMeasurementsBySensorPose(
|
||||||
const Vector3& unbiasedAcc, const Vector3& unbiasedOmega,
|
const Vector3& unbiasedAcc, const Vector3& unbiasedOmega,
|
||||||
OptionalJacobian<3, 3> correctedAcc_H_unbiasedAcc = boost::none,
|
OptionalJacobian<3, 3> correctedAcc_H_unbiasedAcc = {},
|
||||||
OptionalJacobian<3, 3> correctedAcc_H_unbiasedOmega = boost::none,
|
OptionalJacobian<3, 3> correctedAcc_H_unbiasedOmega = {},
|
||||||
OptionalJacobian<3, 3> correctedOmega_H_unbiasedOmega = boost::none) const;
|
OptionalJacobian<3, 3> correctedOmega_H_unbiasedOmega = {}) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update preintegrated measurements and get derivatives
|
* Update preintegrated measurements and get derivatives
|
||||||
|
@ -148,12 +148,12 @@ class GTSAM_EXPORT PreintegrationBase {
|
||||||
/// Given the estimate of the bias, return a NavState tangent vector
|
/// Given the estimate of the bias, return a NavState tangent vector
|
||||||
/// summarizing the preintegrated IMU measurements so far
|
/// summarizing the preintegrated IMU measurements so far
|
||||||
virtual Vector9 biasCorrectedDelta(const imuBias::ConstantBias& bias_i,
|
virtual Vector9 biasCorrectedDelta(const imuBias::ConstantBias& bias_i,
|
||||||
OptionalJacobian<9, 6> H = boost::none) const = 0;
|
OptionalJacobian<9, 6> H = {}) const = 0;
|
||||||
|
|
||||||
/// Predict state at time j
|
/// Predict state at time j
|
||||||
NavState predict(const NavState& state_i, const imuBias::ConstantBias& bias_i,
|
NavState predict(const NavState& state_i, const imuBias::ConstantBias& bias_i,
|
||||||
OptionalJacobian<9, 9> H1 = boost::none,
|
OptionalJacobian<9, 9> H1 = {},
|
||||||
OptionalJacobian<9, 6> H2 = boost::none) const;
|
OptionalJacobian<9, 6> H2 = {}) const;
|
||||||
|
|
||||||
/// Calculate error given navStates
|
/// Calculate error given navStates
|
||||||
Vector9 computeError(const NavState& state_i, const NavState& state_j,
|
Vector9 computeError(const NavState& state_i, const NavState& state_j,
|
||||||
|
@ -167,10 +167,10 @@ class GTSAM_EXPORT PreintegrationBase {
|
||||||
*/
|
*/
|
||||||
Vector9 computeErrorAndJacobians(const Pose3& pose_i, const Vector3& vel_i,
|
Vector9 computeErrorAndJacobians(const Pose3& pose_i, const Vector3& vel_i,
|
||||||
const Pose3& pose_j, const Vector3& vel_j,
|
const Pose3& pose_j, const Vector3& vel_j,
|
||||||
const imuBias::ConstantBias& bias_i, OptionalJacobian<9, 6> H1 =
|
const imuBias::ConstantBias& bias_i,
|
||||||
boost::none, OptionalJacobian<9, 3> H2 = boost::none,
|
OptionalJacobian<9, 6> H1 = {}, OptionalJacobian<9, 3> H2 = {},
|
||||||
OptionalJacobian<9, 6> H3 = boost::none, OptionalJacobian<9, 3> H4 =
|
OptionalJacobian<9, 6> H3 = {}, OptionalJacobian<9, 3> H4 = {},
|
||||||
boost::none, OptionalJacobian<9, 6> H5 = boost::none) const;
|
OptionalJacobian<9, 6> H5 = {}) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Serialization function */
|
/** Serialization function */
|
||||||
|
|
|
@ -140,7 +140,7 @@ TEST( AHRSFactor, PreintegratedAhrsMeasurementsConstructor ) {
|
||||||
EXPECT(assert_equal(gyroscopeCovariance,
|
EXPECT(assert_equal(gyroscopeCovariance,
|
||||||
actualPim.p().getGyroscopeCovariance(), 1e-6));
|
actualPim.p().getGyroscopeCovariance(), 1e-6));
|
||||||
EXPECT(assert_equal(omegaCoriolis,
|
EXPECT(assert_equal(omegaCoriolis,
|
||||||
actualPim.p().getOmegaCoriolis().get(), 1e-6));
|
*(actualPim.p().getOmegaCoriolis()), 1e-6));
|
||||||
EXPECT(assert_equal(bias, actualPim.biasHat(), 1e-6));
|
EXPECT(assert_equal(bias, actualPim.biasHat(), 1e-6));
|
||||||
DOUBLES_EQUAL(deltaTij, actualPim.deltaTij(), 1e-6);
|
DOUBLES_EQUAL(deltaTij, actualPim.deltaTij(), 1e-6);
|
||||||
EXPECT(assert_equal(deltaRij, Rot3(actualPim.deltaRij()), 1e-6));
|
EXPECT(assert_equal(deltaRij, Rot3(actualPim.deltaRij()), 1e-6));
|
||||||
|
@ -163,7 +163,7 @@ TEST(AHRSFactor, Error) {
|
||||||
pim.integrateMeasurement(measuredOmega, deltaT);
|
pim.integrateMeasurement(measuredOmega, deltaT);
|
||||||
|
|
||||||
// Create factor
|
// Create factor
|
||||||
AHRSFactor factor(X(1), X(2), B(1), pim, kZeroOmegaCoriolis, boost::none);
|
AHRSFactor factor(X(1), X(2), B(1), pim, kZeroOmegaCoriolis, {});
|
||||||
|
|
||||||
Vector3 errorActual = factor.evaluateError(x1, x2, bias);
|
Vector3 errorActual = factor.evaluateError(x1, x2, bias);
|
||||||
|
|
||||||
|
@ -458,8 +458,7 @@ TEST (AHRSFactor, predictTest) {
|
||||||
|
|
||||||
// PreintegratedAhrsMeasurements::predict
|
// PreintegratedAhrsMeasurements::predict
|
||||||
Matrix expectedH = numericalDerivative11<Vector3, Vector3>(
|
Matrix expectedH = numericalDerivative11<Vector3, Vector3>(
|
||||||
std::bind(&PreintegratedAhrsMeasurements::predict,
|
[&pim](const Vector3& b) { return pim.predict(b, {}); }, bias);
|
||||||
&pim, std::placeholders::_1, boost::none), bias);
|
|
||||||
|
|
||||||
// Actual Jacobians
|
// Actual Jacobians
|
||||||
Matrix H;
|
Matrix H;
|
||||||
|
|
|
@ -57,8 +57,8 @@ Pose3 body_P3_sensor(Rot3::RzRyRx(Vector3(1.5, 0.9, -1.15)),
|
||||||
|
|
||||||
// *****************************************************************************
|
// *****************************************************************************
|
||||||
TEST(MagPoseFactor, Constructors) {
|
TEST(MagPoseFactor, Constructors) {
|
||||||
MagPoseFactor<Pose2> f2a(Symbol('X', 0), measured2, scale, dir2, bias2, model2, boost::none);
|
MagPoseFactor<Pose2> f2a(Symbol('X', 0), measured2, scale, dir2, bias2, model2, {});
|
||||||
MagPoseFactor<Pose3> f3a(Symbol('X', 0), measured3, scale, dir3, bias3, model3, boost::none);
|
MagPoseFactor<Pose3> f3a(Symbol('X', 0), measured3, scale, dir3, bias3, model3, {});
|
||||||
|
|
||||||
// Try constructing with a body_P_sensor set.
|
// Try constructing with a body_P_sensor set.
|
||||||
MagPoseFactor<Pose2> f2b = MagPoseFactor<Pose2>(
|
MagPoseFactor<Pose2> f2b = MagPoseFactor<Pose2>(
|
||||||
|
@ -75,7 +75,7 @@ TEST(MagPoseFactor, JacobianPose2) {
|
||||||
Matrix H2;
|
Matrix H2;
|
||||||
|
|
||||||
// Error should be zero at the groundtruth pose.
|
// Error should be zero at the groundtruth pose.
|
||||||
MagPoseFactor<Pose2> f(Symbol('X', 0), measured2, scale, dir2, bias2, model2, boost::none);
|
MagPoseFactor<Pose2> f(Symbol('X', 0), measured2, scale, dir2, bias2, model2, {});
|
||||||
CHECK(gtsam::assert_equal(Z_2x1, f.evaluateError(n_P2_b, H2), 1e-5));
|
CHECK(gtsam::assert_equal(Z_2x1, f.evaluateError(n_P2_b, H2), 1e-5));
|
||||||
CHECK(gtsam::assert_equal(gtsam::numericalDerivative11<Vector, Pose2> //
|
CHECK(gtsam::assert_equal(gtsam::numericalDerivative11<Vector, Pose2> //
|
||||||
([&f] (const Pose2& p) {return f.evaluateError(p);},
|
([&f] (const Pose2& p) {return f.evaluateError(p);},
|
||||||
|
@ -88,7 +88,7 @@ TEST(MagPoseFactor, JacobianPose3) {
|
||||||
Matrix H3;
|
Matrix H3;
|
||||||
|
|
||||||
// Error should be zero at the groundtruth pose.
|
// Error should be zero at the groundtruth pose.
|
||||||
MagPoseFactor<Pose3> f(Symbol('X', 0), measured3, scale, dir3, bias3, model3, boost::none);
|
MagPoseFactor<Pose3> f(Symbol('X', 0), measured3, scale, dir3, bias3, model3, {});
|
||||||
CHECK(gtsam::assert_equal(Z_3x1, f.evaluateError(n_P3_b, H3), 1e-5));
|
CHECK(gtsam::assert_equal(Z_3x1, f.evaluateError(n_P3_b, H3), 1e-5));
|
||||||
CHECK(gtsam::assert_equal(gtsam::numericalDerivative11<Vector, Pose3> //
|
CHECK(gtsam::assert_equal(gtsam::numericalDerivative11<Vector, Pose3> //
|
||||||
([&f] (const Pose3& p) {return f.evaluateError(p);},
|
([&f] (const Pose3& p) {return f.evaluateError(p);},
|
||||||
|
|
|
@ -554,7 +554,7 @@ static bool PowerMinimumEigenValue(
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sparse C = pmEigenValue * Matrix::Identity(A.rows(), A.cols()).sparseView() - A;
|
const Sparse C = pmEigenValue * Matrix::Identity(A.rows(), A.cols()).sparseView() - A;
|
||||||
const boost::optional<Vector> initial = perturb(S.row(0));
|
const std::optional<Vector> initial = perturb(S.row(0));
|
||||||
AcceleratedPowerMethod<Sparse> apmShiftedOperator(C, initial);
|
AcceleratedPowerMethod<Sparse> apmShiftedOperator(C, initial);
|
||||||
|
|
||||||
const bool minConverged = apmShiftedOperator.compute(
|
const bool minConverged = apmShiftedOperator.compute(
|
||||||
|
|
Loading…
Reference in New Issue