Python tests
parent
39d1f58eae
commit
f5b57ce59f
|
@ -14,10 +14,10 @@ import unittest
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import SO4
|
from gtsam import SO4
|
||||||
|
|
||||||
id = SO4()
|
I4 = SO4()
|
||||||
v1 = np.array([0.1, 0, 0, 0, 0, 0])
|
v1 = np.array([0, 0, 0, .1, 0, 0])
|
||||||
|
v2 = np.array([0, 0, 0, 0.01, 0.02, 0.03])
|
||||||
Q1 = SO4.Expmap(v1)
|
Q1 = SO4.Expmap(v1)
|
||||||
v2 = np.array([0.01, 0.02, 0.03, 0, 0, 0])
|
|
||||||
Q2 = SO4.Expmap(v2)
|
Q2 = SO4.Expmap(v2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,13 +33,13 @@ class TestSO4(unittest.TestCase):
|
||||||
def test_retract(self):
|
def test_retract(self):
|
||||||
"""Test retraction to manifold."""
|
"""Test retraction to manifold."""
|
||||||
v = np.zeros((6,), np.float)
|
v = np.zeros((6,), np.float)
|
||||||
actual = id.retract(v)
|
actual = I4.retract(v)
|
||||||
self.assertTrue(actual.equals(id, 1e-9))
|
self.assertTrue(actual.equals(I4, 1e-9))
|
||||||
|
|
||||||
def test_local(self):
|
def test_local(self):
|
||||||
"""Check localCoordinates for trivial case."""
|
"""Check localCoordinates for trivial case."""
|
||||||
v0 = np.zeros((6,), np.float)
|
v0 = np.zeros((6,), np.float)
|
||||||
actual = id.localCoordinates(id)
|
actual = I4.localCoordinates(I4)
|
||||||
np.testing.assert_array_almost_equal(actual, v0)
|
np.testing.assert_array_almost_equal(actual, v0)
|
||||||
|
|
||||||
def test_compose(self):
|
def test_compose(self):
|
||||||
|
@ -51,7 +51,7 @@ class TestSO4(unittest.TestCase):
|
||||||
def test_vec(self):
|
def test_vec(self):
|
||||||
"""Check wrapping of vec."""
|
"""Check wrapping of vec."""
|
||||||
expected = np.array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
|
expected = np.array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
|
||||||
actual = id.vec()
|
actual = I4.vec()
|
||||||
np.testing.assert_array_equal(actual, expected)
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
"""
|
||||||
|
GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
|
||||||
|
Atlanta, Georgia 30332-0415
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
See LICENSE for the license information
|
||||||
|
|
||||||
|
Dynamic SO(n) unit tests.
|
||||||
|
Author: Frank Dellaert
|
||||||
|
"""
|
||||||
|
# pylint: disable=no-name-in-module, import-error
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from gtsam import SOn
|
||||||
|
|
||||||
|
I4 = SOn(4)
|
||||||
|
v1 = np.array([0, 0, 0, .1, 0, 0])
|
||||||
|
v2 = np.array([0, 0, 0, 0.01, 0.02, 0.03])
|
||||||
|
Q1 = I4.retract(v1)
|
||||||
|
Q2 = I4.retract(v2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestSO4(unittest.TestCase):
|
||||||
|
"""Test selected SOn methods."""
|
||||||
|
|
||||||
|
def test_constructor(self):
|
||||||
|
"""Construct from matrix."""
|
||||||
|
matrix = np.eye(4)
|
||||||
|
so4 = SOn.FromMatrix(matrix)
|
||||||
|
self.assertIsInstance(so4, SOn)
|
||||||
|
|
||||||
|
def test_retract(self):
|
||||||
|
"""Test retraction to manifold."""
|
||||||
|
v = np.zeros((6,), np.float)
|
||||||
|
actual = I4.retract(v)
|
||||||
|
self.assertTrue(actual.equals(I4, 1e-9))
|
||||||
|
|
||||||
|
def test_local(self):
|
||||||
|
"""Check localCoordinates for trivial case."""
|
||||||
|
v0 = np.zeros((6,), np.float)
|
||||||
|
actual = I4.localCoordinates(I4)
|
||||||
|
np.testing.assert_array_almost_equal(actual, v0)
|
||||||
|
|
||||||
|
def test_compose(self):
|
||||||
|
"""Check compose works in subgroup."""
|
||||||
|
expected = I4.retract(2*v1)
|
||||||
|
actual = Q1.compose(Q1)
|
||||||
|
self.assertTrue(actual.equals(expected, 1e-3)) # not exmap so only approximate
|
||||||
|
|
||||||
|
def test_vec(self):
|
||||||
|
"""Check wrapping of vec."""
|
||||||
|
expected = np.array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
|
||||||
|
actual = I4.vec()
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
19
gtsam.h
19
gtsam.h
|
@ -542,6 +542,7 @@ class SO3 {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
SO3();
|
SO3();
|
||||||
SO3(Matrix R);
|
SO3(Matrix R);
|
||||||
|
static gtsam::SO3 FromMatrix(Matrix R);
|
||||||
static gtsam::SO3 AxisAngle(const Vector axis, double theta);
|
static gtsam::SO3 AxisAngle(const Vector axis, double theta);
|
||||||
static gtsam::SO3 ClosestTo(const Matrix M);
|
static gtsam::SO3 ClosestTo(const Matrix M);
|
||||||
|
|
||||||
|
@ -570,6 +571,7 @@ class SO4 {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
SO4();
|
SO4();
|
||||||
SO4(Matrix R);
|
SO4(Matrix R);
|
||||||
|
static gtsam::SO4 FromMatrix(Matrix R);
|
||||||
|
|
||||||
// Testable
|
// Testable
|
||||||
void print(string s) const;
|
void print(string s) const;
|
||||||
|
@ -595,7 +597,22 @@ class SO4 {
|
||||||
class SOn {
|
class SOn {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
SOn(size_t n);
|
SOn(size_t n);
|
||||||
SOn(Matrix R);
|
static gtsam::SOn FromMatrix(Matrix R);
|
||||||
|
|
||||||
|
// Testable
|
||||||
|
void print(string s) const;
|
||||||
|
bool equals(const gtsam::SOn& other, double tol) const;
|
||||||
|
|
||||||
|
// Group
|
||||||
|
static gtsam::SOn identity();
|
||||||
|
gtsam::SOn inverse() const;
|
||||||
|
gtsam::SOn between(const gtsam::SOn& Q) const;
|
||||||
|
gtsam::SOn compose(const gtsam::SOn& Q) const;
|
||||||
|
|
||||||
|
// Manifold
|
||||||
|
gtsam::SOn retract(Vector v) const;
|
||||||
|
Vector localCoordinates(const gtsam::SOn& Q) const;
|
||||||
|
static gtsam::SOn Expmap(Vector v);
|
||||||
|
|
||||||
// Other methods
|
// Other methods
|
||||||
Vector vec() const;
|
Vector vec() const;
|
||||||
|
|
|
@ -76,14 +76,21 @@ class SO : public LieGroup<SO<N>, internal::DimensionSO(N)> {
|
||||||
/// Construct SO<N> identity for N == Eigen::Dynamic
|
/// Construct SO<N> identity for N == Eigen::Dynamic
|
||||||
template <int N_ = N, typename = IsDynamic<N_>>
|
template <int N_ = N, typename = IsDynamic<N_>>
|
||||||
explicit SO(size_t n = 0) {
|
explicit SO(size_t n = 0) {
|
||||||
if (n == 0) throw std::runtime_error("SO: Dimensionality not known.");
|
// We allow for n=0 as the default constructor, needed for serialization,
|
||||||
|
// wrappers etc.
|
||||||
matrix_ = Eigen::MatrixXd::Identity(n, n);
|
matrix_ = Eigen::MatrixXd::Identity(n, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor from Eigen Matrix
|
/// Constructor from Eigen Matrix, dynamic version
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
explicit SO(const Eigen::MatrixBase<Derived>& R) : matrix_(R.eval()) {}
|
explicit SO(const Eigen::MatrixBase<Derived>& R) : matrix_(R.eval()) {}
|
||||||
|
|
||||||
|
/// Named constructor from Eigen Matrix
|
||||||
|
template <typename Derived>
|
||||||
|
static SO FromMatrix(const Eigen::MatrixBase<Derived>& R) {
|
||||||
|
return SO(R);
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct dynamic SO(n) from Fixed SO<M>
|
/// Construct dynamic SO(n) from Fixed SO<M>
|
||||||
template <int M, int N_ = N, typename = IsDynamic<N_>>
|
template <int M, int N_ = N, typename = IsDynamic<N_>>
|
||||||
explicit SO(const SO<M>& R) : matrix_(R.matrix()) {}
|
explicit SO(const SO<M>& R) : matrix_(R.matrix()) {}
|
||||||
|
|
Loading…
Reference in New Issue