Specialized Hat/Vee
							parent
							
								
									d376d0158d
								
							
						
					
					
						commit
						ab1be9c4de
					
				|  | @ -22,62 +22,16 @@ | ||||||
| 
 | 
 | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
|  | // Implementation for N>5 just uses dynamic version
 | ||||||
| template <int N> | template <int N> | ||||||
| Matrix SO<N>::Hat(const Vector& xi) { | typename SO<N>::MatrixNN SO<N>::Hat(const TangentVector& xi) { | ||||||
|   size_t n = AmbientDim(xi.size()); |   return SOn::Hat(xi); | ||||||
|   if (n < 2) throw std::invalid_argument("SO<N>::Hat: n<2 not supported"); |  | ||||||
| 
 |  | ||||||
|   Matrix X(n, n);  // allocate space for n*n skew-symmetric matrix
 |  | ||||||
|   X.setZero(); |  | ||||||
|   if (n == 2) { |  | ||||||
|     // Handle SO(2) case as recursion bottom
 |  | ||||||
|     assert(xi.size() == 1); |  | ||||||
|     X << 0, -xi(0), xi(0), 0; |  | ||||||
|   } else { |  | ||||||
|     // Recursively call SO(n-1) call for top-left block
 |  | ||||||
|     const size_t dmin = (n - 1) * (n - 2) / 2; |  | ||||||
|     X.topLeftCorner(n - 1, n - 1) = Hat(xi.tail(dmin)); |  | ||||||
| 
 |  | ||||||
|     // Now fill last row and column
 |  | ||||||
|     double sign = 1.0; |  | ||||||
|     for (size_t i = 0; i < n - 1; i++) { |  | ||||||
|       const size_t j = n - 2 - i; |  | ||||||
|       X(n - 1, j) = sign * xi(i); |  | ||||||
|       X(j, n - 1) = -X(n - 1, j); |  | ||||||
|       sign = -sign; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return X; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Implementation for N>5 just uses dynamic version
 | ||||||
| template <int N> | template <int N> | ||||||
| Vector SO<N>::Vee(const Matrix& X) { | typename SO<N>::TangentVector SO<N>::Vee(const MatrixNN& X) { | ||||||
|   const size_t n = X.rows(); |   return SOn::Vee(X); | ||||||
|   if (n < 2) throw std::invalid_argument("SO<N>::Hat: n<2 not supported"); |  | ||||||
| 
 |  | ||||||
|   if (n == 2) { |  | ||||||
|     // Handle SO(2) case as recursion bottom
 |  | ||||||
|     Vector xi(1); |  | ||||||
|     xi(0) = X(1, 0); |  | ||||||
|     return xi; |  | ||||||
|   } else { |  | ||||||
|     // Calculate dimension and allocate space
 |  | ||||||
|     const size_t d = n * (n - 1) / 2; |  | ||||||
|     Vector xi(d); |  | ||||||
| 
 |  | ||||||
|     // Fill first n-1 spots from last row of X
 |  | ||||||
|     double sign = 1.0; |  | ||||||
|     for (size_t i = 0; i < n - 1; i++) { |  | ||||||
|       const size_t j = n - 2 - i; |  | ||||||
|       xi(i) = sign * X(n - 1, j); |  | ||||||
|       sign = -sign; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Recursively call Vee to fill remainder of x
 |  | ||||||
|     const size_t dmin = (n - 1) * (n - 2) / 2; |  | ||||||
|     xi.tail(dmin) = Vee(X.topLeftCorner(n - 1, n - 1)); |  | ||||||
|     return xi; |  | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <int N> | template <int N> | ||||||
|  |  | ||||||
|  | @ -20,6 +20,64 @@ | ||||||
| 
 | 
 | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
|  | template <> | ||||||
|  | Matrix SOn::Hat(const Vector& xi) { | ||||||
|  |   size_t n = AmbientDim(xi.size()); | ||||||
|  |   if (n < 2) throw std::invalid_argument("SO<N>::Hat: n<2 not supported"); | ||||||
|  | 
 | ||||||
|  |   Matrix X(n, n);  // allocate space for n*n skew-symmetric matrix
 | ||||||
|  |   X.setZero(); | ||||||
|  |   if (n == 2) { | ||||||
|  |     // Handle SO(2) case as recursion bottom
 | ||||||
|  |     assert(xi.size() == 1); | ||||||
|  |     X << 0, -xi(0), xi(0), 0; | ||||||
|  |   } else { | ||||||
|  |     // Recursively call SO(n-1) call for top-left block
 | ||||||
|  |     const size_t dmin = (n - 1) * (n - 2) / 2; | ||||||
|  |     X.topLeftCorner(n - 1, n - 1) = Hat(xi.tail(dmin)); | ||||||
|  | 
 | ||||||
|  |     // Now fill last row and column
 | ||||||
|  |     double sign = 1.0; | ||||||
|  |     for (size_t i = 0; i < n - 1; i++) { | ||||||
|  |       const size_t j = n - 2 - i; | ||||||
|  |       X(n - 1, j) = sign * xi(i); | ||||||
|  |       X(j, n - 1) = -X(n - 1, j); | ||||||
|  |       sign = -sign; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return X; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | Vector SOn::Vee(const Matrix& X) { | ||||||
|  |   const size_t n = X.rows(); | ||||||
|  |   if (n < 2) throw std::invalid_argument("SO<N>::Hat: n<2 not supported"); | ||||||
|  | 
 | ||||||
|  |   if (n == 2) { | ||||||
|  |     // Handle SO(2) case as recursion bottom
 | ||||||
|  |     Vector xi(1); | ||||||
|  |     xi(0) = X(1, 0); | ||||||
|  |     return xi; | ||||||
|  |   } else { | ||||||
|  |     // Calculate dimension and allocate space
 | ||||||
|  |     const size_t d = n * (n - 1) / 2; | ||||||
|  |     Vector xi(d); | ||||||
|  | 
 | ||||||
|  |     // Fill first n-1 spots from last row of X
 | ||||||
|  |     double sign = 1.0; | ||||||
|  |     for (size_t i = 0; i < n - 1; i++) { | ||||||
|  |       const size_t j = n - 2 - i; | ||||||
|  |       xi(i) = sign * X(n - 1, j); | ||||||
|  |       sign = -sign; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Recursively call Vee to fill remainder of x
 | ||||||
|  |     const size_t dmin = (n - 1) * (n - 2) / 2; | ||||||
|  |     xi.tail(dmin) = Vee(X.topLeftCorner(n - 1, n - 1)); | ||||||
|  |     return xi; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| template <> | template <> | ||||||
| SOn LieGroup<SOn, Eigen::Dynamic>::compose(const SOn& g, DynamicJacobian H1, | SOn LieGroup<SOn, Eigen::Dynamic>::compose(const SOn& g, DynamicJacobian H1, | ||||||
|                                            DynamicJacobian H2) const { |                                            DynamicJacobian H2) const { | ||||||
|  |  | ||||||
|  | @ -83,6 +83,10 @@ class SO : public LieGroup<SO<N>, internal::DimensionSO(N)> { | ||||||
|   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()) {} | ||||||
| 
 | 
 | ||||||
|  |   /// Construct dynamic SO(n) from Fixed SO<M>
 | ||||||
|  |   template <int M, int N_ = N, typename = IsDynamic<N_>> | ||||||
|  |   explicit SO(const SO<M>& R) : matrix_(R.matrix()) {} | ||||||
|  | 
 | ||||||
|   /// Constructor from AngleAxisd
 |   /// Constructor from AngleAxisd
 | ||||||
|   template <int N_ = N, typename = IsSO3<N_>> |   template <int N_ = N, typename = IsSO3<N_>> | ||||||
|   SO(const Eigen::AngleAxisd& angleAxis) : matrix_(angleAxis) {} |   SO(const Eigen::AngleAxisd& angleAxis) : matrix_(angleAxis) {} | ||||||
|  | @ -188,12 +192,12 @@ class SO : public LieGroup<SO<N>, internal::DimensionSO(N)> { | ||||||
|    *  -d  c -b  a  0 |    *  -d  c -b  a  0 | ||||||
|    * This scheme behaves exactly as expected for SO(2) and SO(3). |    * This scheme behaves exactly as expected for SO(2) and SO(3). | ||||||
|    */ |    */ | ||||||
|   static Matrix Hat(const Vector& xi); |   static MatrixNN Hat(const TangentVector& xi); | ||||||
| 
 | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * Inverse of Hat. See note about xi element order in Hat. |    * Inverse of Hat. See note about xi element order in Hat. | ||||||
|    */ |    */ | ||||||
|   static Vector Vee(const Matrix& X); |   static TangentVector Vee(const MatrixNN& X); | ||||||
| 
 | 
 | ||||||
|   // Chart at origin
 |   // Chart at origin
 | ||||||
|   struct ChartAtOrigin { |   struct ChartAtOrigin { | ||||||
|  | @ -259,8 +263,20 @@ class SO : public LieGroup<SO<N>, internal::DimensionSO(N)> { | ||||||
| using SOn = SO<Eigen::Dynamic>; | using SOn = SO<Eigen::Dynamic>; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Fully specialize compose and between, because the derivative is unknowable by |  * Specialize dynamic Hat and Vee, because recursion depends on dynamic nature. | ||||||
|  * the LieGroup implementations, who return a fixed-size matrix for H2. |  * The definition is in SOn.cpp. Fixed-size SO3 and SO4 have their own version, | ||||||
|  |  * and implementation for other fixed N is in SOn-inl.h. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | Matrix SOn::Hat(const Vector& xi); | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | Vector SOn::Vee(const Matrix& X); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Specialize dynamic compose and between, because the derivative is unknowable | ||||||
|  |  * by the LieGroup implementations, who return a fixed-size matrix for H2. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| using DynamicJacobian = OptionalJacobian<Eigen::Dynamic, Eigen::Dynamic>; | using DynamicJacobian = OptionalJacobian<Eigen::Dynamic, Eigen::Dynamic>; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue