build_manifold.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // This is an advanced implementation of the algorithm described in the
  2. // following paper:
  3. // C. Hertzberg, R. Wagner, U. Frese, and L. Schroder. Integratinggeneric sensor fusion algorithms with sound state representationsthrough encapsulation of manifolds.
  4. // CoRR, vol. abs/1107.1119, 2011.[Online]. Available: http://arxiv.org/abs/1107.1119
  5. /*
  6. * Copyright (c) 2019--2023, The University of Hong Kong
  7. * All rights reserved.
  8. *
  9. * Modifier: Dongjiao HE <hdj65822@connect.hku.hk>
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * * Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * * Redistributions in binary form must reproduce the above
  18. * copyright notice, this list of conditions and the following
  19. * disclaimer in the documentation and/or other materials provided
  20. * with the distribution.
  21. * * Neither the name of the Universitaet Bremen nor the names of its
  22. * contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  28. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  29. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  30. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  31. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  32. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  33. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  35. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. */
  38. /*
  39. * Copyright (c) 2008--2011, Universitaet Bremen
  40. * All rights reserved.
  41. *
  42. * Author: Christoph Hertzberg <chtz@informatik.uni-bremen.de>
  43. *
  44. * Redistribution and use in source and binary forms, with or without
  45. * modification, are permitted provided that the following conditions
  46. * are met:
  47. *
  48. * * Redistributions of source code must retain the above copyright
  49. * notice, this list of conditions and the following disclaimer.
  50. * * Redistributions in binary form must reproduce the above
  51. * copyright notice, this list of conditions and the following
  52. * disclaimer in the documentation and/or other materials provided
  53. * with the distribution.
  54. * * Neither the name of the Universitaet Bremen nor the names of its
  55. * contributors may be used to endorse or promote products derived
  56. * from this software without specific prior written permission.
  57. *
  58. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  59. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  60. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  61. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  62. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  63. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  64. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  65. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  66. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  67. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  68. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  69. * POSSIBILITY OF SUCH DAMAGE.
  70. */
  71. /**
  72. * @file mtk/build_manifold.hpp
  73. * @brief Macro to automatically construct compound manifolds.
  74. *
  75. */
  76. #ifndef MTK_AUTOCONSTRUCT_HPP_
  77. #define MTK_AUTOCONSTRUCT_HPP_
  78. #include <vector>
  79. #include <boost/preprocessor/seq.hpp>
  80. #include <boost/preprocessor/cat.hpp>
  81. #include <Eigen/Core>
  82. #include "src/SubManifold.hpp"
  83. #include "startIdx.hpp"
  84. #ifndef PARSED_BY_DOXYGEN
  85. //////// internals //////
  86. #define MTK_APPLY_MACRO_ON_TUPLE(r, macro, tuple) macro tuple
  87. #define MTK_TRANSFORM_COMMA(macro, entries) BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM_S(1, MTK_APPLY_MACRO_ON_TUPLE, macro, entries))
  88. #define MTK_TRANSFORM(macro, entries) BOOST_PP_SEQ_FOR_EACH_R(1, MTK_APPLY_MACRO_ON_TUPLE, macro, entries)
  89. #define MTK_CONSTRUCTOR_ARG( type, id) const type& id = type()
  90. #define MTK_CONSTRUCTOR_COPY( type, id) id(id)
  91. #define MTK_BOXPLUS( type, id) id.boxplus(MTK::subvector(__vec, &self::id), __scale);
  92. #define MTK_OPLUS( type, id) id.oplus(MTK::subvector_(__vec, &self::id), __scale);
  93. #define MTK_BOXMINUS( type, id) id.boxminus(MTK::subvector(__res, &self::id), __oth.id);
  94. #define MTK_S2_hat( type, id) if(id.IDX == idx){id.S2_hat(res);}
  95. #define MTK_S2_Nx_yy( type, id) if(id.IDX == idx){id.S2_Nx_yy(res);}
  96. #define MTK_S2_Mx( type, id) if(id.IDX == idx){id.S2_Mx(res, dx);}
  97. #define MTK_OSTREAM( type, id) << __var.id << " "
  98. #define MTK_ISTREAM( type, id) >> __var.id
  99. #define MTK_S2_state( type, id) if(id.TYP == 1){S2_state.push_back(std::make_pair(id.IDX, id.DIM));}
  100. #define MTK_SO3_state( type, id) if(id.TYP == 2){(SO3_state).push_back(std::make_pair(id.IDX, id.DIM));}
  101. #define MTK_vect_state( type, id) if(id.TYP == 0){(vect_state).push_back(std::make_pair(std::make_pair(id.IDX, id.DIM), type::DOF));}
  102. #define MTK_SUBVARLIST(seq, S2state, SO3state) \
  103. BOOST_PP_FOR_1( \
  104. ( \
  105. BOOST_PP_SEQ_SIZE(seq), \
  106. BOOST_PP_SEQ_HEAD(seq), \
  107. BOOST_PP_SEQ_TAIL(seq) (~), \
  108. 0,\
  109. 0,\
  110. S2state,\
  111. SO3state ),\
  112. MTK_ENTRIES_TEST, MTK_ENTRIES_NEXT, MTK_ENTRIES_OUTPUT)
  113. #define MTK_PUT_TYPE(type, id, dof, dim, S2state, SO3state) \
  114. MTK::SubManifold<type, dof, dim> id;
  115. #define MTK_PUT_TYPE_AND_ENUM(type, id, dof, dim, S2state, SO3state) \
  116. MTK_PUT_TYPE(type, id, dof, dim, S2state, SO3state) \
  117. enum {DOF = type::DOF + dof}; \
  118. enum {DIM = type::DIM+dim}; \
  119. typedef type::scalar scalar;
  120. #define MTK_ENTRIES_OUTPUT(r, state) MTK_ENTRIES_OUTPUT_I state
  121. #define MTK_ENTRIES_OUTPUT_I(s, head, seq, dof, dim, S2state, SO3state) \
  122. MTK_APPLY_MACRO_ON_TUPLE(~, \
  123. BOOST_PP_IF(BOOST_PP_DEC(s), MTK_PUT_TYPE, MTK_PUT_TYPE_AND_ENUM), \
  124. ( BOOST_PP_TUPLE_REM_2 head, dof, dim, S2state, SO3state))
  125. #define MTK_ENTRIES_TEST(r, state) MTK_TUPLE_ELEM_4_0 state
  126. //! this used to be BOOST_PP_TUPLE_ELEM_4_0:
  127. #define MTK_TUPLE_ELEM_4_0(a,b,c,d,e,f, g) a
  128. #define MTK_ENTRIES_NEXT(r, state) MTK_ENTRIES_NEXT_I state
  129. #define MTK_ENTRIES_NEXT_I(len, head, seq, dof, dim, S2state, SO3state) ( \
  130. BOOST_PP_DEC(len), \
  131. BOOST_PP_SEQ_HEAD(seq), \
  132. BOOST_PP_SEQ_TAIL(seq), \
  133. dof + BOOST_PP_TUPLE_ELEM_2_0 head::DOF,\
  134. dim + BOOST_PP_TUPLE_ELEM_2_0 head::DIM,\
  135. S2state,\
  136. SO3state)
  137. #endif /* not PARSED_BY_DOXYGEN */
  138. /**
  139. * Construct a manifold.
  140. * @param name is the class-name of the manifold,
  141. * @param entries is the list of sub manifolds
  142. *
  143. * Entries must be given in a list like this:
  144. * @code
  145. * typedef MTK::trafo<MTK::SO3<double> > Pose;
  146. * typedef MTK::vect<double, 3> Vec3;
  147. * MTK_BUILD_MANIFOLD(imu_state,
  148. * ((Pose, pose))
  149. * ((Vec3, vel))
  150. * ((Vec3, acc_bias))
  151. * )
  152. * @endcode
  153. * Whitespace is optional, but the double parentheses are necessary.
  154. * Construction is done entirely in preprocessor.
  155. * After construction @a name is also a manifold. Its members can be
  156. * accessed by names given in @a entries.
  157. *
  158. * @note Variable types are not allowed to have commas, thus types like
  159. * @c vect<double, 3> need to be typedef'ed ahead.
  160. */
  161. #define MTK_BUILD_MANIFOLD(name, entries) \
  162. struct name { \
  163. typedef name self; \
  164. std::vector<std::pair<int, int> > S2_state;\
  165. std::vector<std::pair<int, int> > SO3_state;\
  166. std::vector<std::pair<std::pair<int, int>, int> > vect_state;\
  167. MTK_SUBVARLIST(entries, S2_state, SO3_state) \
  168. name ( \
  169. MTK_TRANSFORM_COMMA(MTK_CONSTRUCTOR_ARG, entries) \
  170. ) : \
  171. MTK_TRANSFORM_COMMA(MTK_CONSTRUCTOR_COPY, entries) {}\
  172. int getDOF() const { return DOF; } \
  173. void boxplus(const MTK::vectview<const scalar, DOF> & __vec, scalar __scale = 1 ) { \
  174. MTK_TRANSFORM(MTK_BOXPLUS, entries)\
  175. } \
  176. void oplus(const MTK::vectview<const scalar, DIM> & __vec, scalar __scale = 1 ) { \
  177. MTK_TRANSFORM(MTK_OPLUS, entries)\
  178. } \
  179. void boxminus(MTK::vectview<scalar,DOF> __res, const name& __oth) const { \
  180. MTK_TRANSFORM(MTK_BOXMINUS, entries)\
  181. } \
  182. friend std::ostream& operator<<(std::ostream& __os, const name& __var){ \
  183. return __os MTK_TRANSFORM(MTK_OSTREAM, entries); \
  184. } \
  185. void build_S2_state(){\
  186. MTK_TRANSFORM(MTK_S2_state, entries)\
  187. }\
  188. void build_vect_state(){\
  189. MTK_TRANSFORM(MTK_vect_state, entries)\
  190. }\
  191. void build_SO3_state(){\
  192. MTK_TRANSFORM(MTK_SO3_state, entries)\
  193. }\
  194. void S2_hat(Eigen::Matrix<scalar, 3, 3> &res, int idx) {\
  195. MTK_TRANSFORM(MTK_S2_hat, entries)\
  196. }\
  197. void S2_Nx_yy(Eigen::Matrix<scalar, 2, 3> &res, int idx) {\
  198. MTK_TRANSFORM(MTK_S2_Nx_yy, entries)\
  199. }\
  200. void S2_Mx(Eigen::Matrix<scalar, 3, 2> &res, Eigen::Matrix<scalar, 2, 1> dx, int idx) {\
  201. MTK_TRANSFORM(MTK_S2_Mx, entries)\
  202. }\
  203. friend std::istream& operator>>(std::istream& __is, name& __var){ \
  204. return __is MTK_TRANSFORM(MTK_ISTREAM, entries); \
  205. } \
  206. };
  207. #endif /*MTK_AUTOCONSTRUCT_HPP_*/